I am currently programming an arduino and am using C++ objects to do so. I've run into a weird issue when I try to multiply the values that are being pointed at. Referring to the code below, when I run the program, var3 and var4 end up having two different values. Why is this? They are essentially multiplying the same values (or so I believe). Any help?
long var1 = info->accelXYZ[0];
long var2 = info->taughtAccelXYZ[0];
long var3 = var1*var2;
long var4 = info->accelXYZ[0]*info->taughtAccelXYZ[0];
It's possible you're overflowing in one of the situations.
The multiplication of var1 and var2 (both long) gives a long which is then loaded into var3.
If both info->accelXYZ[0] and info->taughtAccelXYZ[0] are int (for example), the result of the multiplication will be int which is then loaded into a long.
The intermediate int form may be overflowing, something you can see in the following snippet:
#include <stdio.h>
#include <limits.h>
int main(void) {
printf("int has %d bytes\n",sizeof(int));
printf("long has %d bytes\n",sizeof(long));
int a = INT_MAX;
int b = 2;
long var1 = a;
long var2 = b;
long var3 = a * b;
long var4 = var1 * var2;
printf ("var3=%ld\n", var3);
printf ("var4=%ld\n", var4);
return 0;
}
which outputs:
int has 4 bytes
long has 8 bytes
var3=-2
var4=4294967294
One reason why var3 may end up with a different value than var4 is integer overflow. This happens when both multiplicands fit in an int, but the product doesn't.
Since ints and longs have different sizes on Arduino Uno*, the computation of var3 is different from computation of var4.
When you compute var3, the multiplication is done in longs on the initial values that fit in an int, so the result of multiplication is not translated. When you compute var4, the computation is done in ints, and then promoted to long. However, by then the result is already truncated, which results in the discrepancy that you are observing.
To make var4 the same correct value as var3, add a cast to long to one of the multiplicands, like this:
long var4 = (info->accelXYZ[0])*((long)info->taughtAccelXYZ[0]);
* int has 16 bits, while long has 32 bits.
Related
I noticed that Stata estimates slightly different sums depending on the level of aggregation of the summands.
To use an example, I have 4 variables (Var1, Var2, Var3, Var4).
Var1 Var2 Var3 Var4
420966 10804428 21982560 1055822272
207381 20133238 69127000 580531008
217297.6 7946694.5 23631250 554597952
327553.2 7505444 10898800 261170592
119776.4 715082.75 607820.3125 414926752
3758613 2533234.5 225734784 88380432
First, I estimate the sum of all 4 variables:
gen sumVars1234 = Var1 + Var2 + Var3 + Var4
// this calculates the same sum as `egen rowtotal`
Then I estimate the sum of Vars 1 and 2, and Vars 3 and 4, separately:
gen sumVars12 = Var1 + Var2
gen sumVars34 = Var3 + Var4
When I add together sumVars12 and sumVars34, this generates sumVars12_34:
gen sumVars12_34 = sumVars12 + sumVars34
gen dif = sumVars12_34 - sumVars1234 // I calculate difference between both sums
However, sumVars12_34 does NOT equal sumVars1234 and I don't understand why.
sumVars12 sumVars34 sumVars12_34 sumVars1234 dif
11225394 1077804800 1089030144 1089030272 -128
20340618 649657984 669998592 669998656 -64
8163992 578229184 586393152 586393216 -64
7832997 272069376 279902368 279902400 -32
834859.125 415534560 416369408 416369440 -32
6291848 314115200 320407040 320407072 -32
I know these differences are very small, and I'm sure there's a simple explanation, but I'm not sure what it is! Any insight would be very much appreciated. Thanks!
It's most likely due to "mixed math" (integers and real floating point type variables). You have digit precision in the input data which also contains Integers, so it's probably due to rounding. I would replicate the calculations in Excel, but only if .0 was added to your whole integers. In Excel, as you may know, you can select all the data in a range of cells, right-click, then select Format Cells-->Number, and specify 1 for Decimal Places. And then do your summing.
I am writing some code for an Arduino project I am working on, and the multiplication is returning me incorrect values, and I can't figure out why.
String calculateShutterSpeed(float fs, int i, int l){
float fstop = fs;
int iso = i;
int lux = l;
float c = 1.00;
float shutterspeedTop = 0;
double shutterspeedBottom = 0;
shutterspeedTop = pow(fs, 2)*c;
shutterspeedBottom = lux*iso;
shutterspeedBottom = shutterspeedBottom/shutterspeedTop;
The code giving me the error is the line where I multiply lux by iso, in some cases (with small numbers) it works fine, but as soon as I use larger numbers it starts giving me incorrect numbers, such as a lux of 4833 and iso of 200 will give me a result of -16440.
Depending on what board you have, the size of an int will be either two or four bytes.
Multiplying two 2-byte integers together produces another 2-byte integer and, when too large for the range, overflows; this is the behavior you're seeing.
You'll have to go to a long or, might as well, a double.
An int type can hold numbers up to a limit.
In your case that seems to be 2^16 = 65536 numbers which means you can have numbers in range [-32,768, 32,767].
You can use long type to resolve the problem.
Quick note:
short = 2-byte
long = 4-byte
int = 2-byte or 4-byte (depending on architecture)
Thanks to ChiefTwoPencils for pointing out ambiquity!
I have the following code:
int32 var1 = 81;
double var2 = 2;
if ((var1/10) < (var1 + var2) / 10)
{
some code to execute;
}
As far as my understanding goes, when dividing it removes the remainder so the if statement should be resolving to "if 8 < 8 then execute" and so shouldn't execute but it does, bit stumped here. Is it because I am using different variable types?
I have tried printing the results of (var1/10) and (var1 + var2) / 10 separately and they both output 8 to the console.
Is it because I am using different variable types?
Yes that is correct:
var1/10 is 8 (integer division)
(var1 + var2) / 10 is 8.3 (floating point division; var1 is promoted to a floating point).
In the evaluation of the if, 8 is promoted to floating point.
8.0 < 8.3 is true. So the if statement executes.
and they both output 8 to the console.
No they don't.
I have the following UINT8 variables:
UINT8 var1 = 0b00000001; //0000 0001
UINT8 var2 = 0b00000011; //0000 0011
UINT8 var3 = 0b00000111; //0000 0111
UINT8 var4 = 0b00001111; //0000 1111
I would like to pack these four UINT8 variables into one UINT32 variable with the following value:
UINT32 var1 = 0b00000001000000110000011100001111; //00000001 00000011 00000111 00001111
Would the following code do it correctly and safely?
UINT32 var1 = (var1<<24) + (var2<<16) + (var3<<8) + var4;
Short answer, yes.
I'm not going to worry about how you wrote your binary numbers. I will enter them in hex and let you look for binary representations by this related SO question: Can I use a binary literal in C or C++?
#include "stdafx.h" // you are using devstudio
#include <Windows.h> // you are using windows types
#include <iostream> // I print out the result
#include <bitset> // I use bitset to print the binary string
int main()
{
UINT8 var1 = 0x01; //0000 0001
UINT8 var2 = 0x03; //0000 0011
UINT8 var3 = 0x07; //0000 0111
UINT8 var4 = 0x0F; //0000 1111
UINT32 bigvar = (var1 << 24) + (var2 << 16) + (var3 << 8) + var4;
std::cout << std::bitset<32>(bigvar) << std::endl;
}
Your math is correct and safe. The bytes are independently declared, so you don't have to worry about byte order. The types are all unsigned, so no UB issues with the sign bit. The shifts all fit in the correct bit count, so no overflow. I generated:
00000001000000110000011100001111
Alternatively, you could have read in a 32 bit integer as 4 bytes, and reconstructed the 32 bit number, but that would not be portable, because sometimes the numbers are stored in reverse order. For example, in TIFF, you read in a header value which tells you whether you would put var1 first and count up, or var4 first and count down. Byte order is something you have to watch out for in almost all practical applications of combining a bunch of bytes into a larger integer type. Look up big-endian and little-endian for more info.
I want to put the number in the left hand side of the float point in a new variable
from a float number ex:
int var1;
float var2;
float x=12.505; // i want the number 12 to put it in "var1" and 0.505 in "var2"
It's very simple if you know that when you convert a floating point value to an integer, it simply truncates the floating point value. So you could simply do
var1 = x; // Assign 12 to var1
var2 = x - var1; // Assigns 12.505 - 12 to var2
var1 = x; // var1 is 12
var2 = x - var1; // var2 is 0.505
Run live.
Note that,
If the conversion is from a floating-point type to an integer type, the value is truncated (the decimal part is removed). If the result lies outside the range of representable values by the type, the conversion causes undefined behavior.
Read more about Type conversions.
You can cast the float to int, using one of the options below:
var1 = (int)x;
var1 = static_cast<int>(x);
var1 = int(x);
All these options are identical. Also, you can use implicit conversion, but it can cause compile warnings or errors depending on your compiler settings:
var1 = x;
After this conversion you will need to calculate the fractional part:
var2 = x - var1;
Please note that direct conversion to int truncates the fractional part, I mean,
(int)(12.505) == 12
(int)(12.499) == 12
(int)(-12.55) == -12
(int)(-12.49) == -12
If you need some other ways of rounding the number, use ceil(), floor() or round(). These functions are located in header file in std namespace.
There are various ways.
For one way, look up the function modf() in the standard header <math.h>
Just use auto truncate functionality.
float f = 12.93;
int b = f; // 12
float p = f - b // 0.93