LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

overflow in interim results of mixed data types

Solved!
Go to solution

Dear all,

 

I am sorry, this is a very basic question...

 

I have the following expression giving me an unexpected result due to overflow:

 

d1 = RoundRealToNearestInteger ( l1 * i1 / l2 );

 

d1 is of type double, l1, l2 of type long int, and i1 of type ssize_t (on a 32 bit machine, i.e. signed int);

 

using e.g. the numeric values l1=14577, l2=1568, i1=156142 I end up with d1 being negative (-1.287554e6);

this occurs if the result of the multiplication is larger than 31 bit (signed int).

 

Actually I would have expected that the intermediate result would be of type long int (long int times int) or of type double (implicit cast) but it seems to be of type int...

 

Is there any 'rule' what intermediate data type is used and can be expected in such cases?

 

Btw, I am aware that I can avoid the problem by rearranging the calculation: l1 / l2 * i1 Smiley Wink

 

Thanks!

0 Kudos
Message 1 of 5
(3,448 Views)

I'm also interested in this.  I've done casting in the past and playing with this has shown some interesting results.

 

 

long I1 = 14577,I2=1568;

ssize_t i1 = 156142;

 

 

 

double d0 = RoundRealToNearestInteger(I1 * i1 / I2);
double d1 = RoundRealToNearestInteger((double)(I1) * i1 / I2);
double d2 = RoundRealToNearestInteger(I1/I2 * i1);
double d3 = RoundRealToNearestInteger((double)I1 * (double)i1 / I2);
double d4 = RoundRealToNearestInteger((double)I1 / (double)I2 * (double)i1);
d0 = -1287554
d1 = d3 = d4 =  1451583
d2 = 1405278
Without thinking about it, I would have guessed d2=d4

 

0 Kudos
Message 2 of 5
(3,440 Views)
Solution
Accepted by topic author Wolfgang

Wolfgang,

 

The basic C rule for these arithmetic calculations is that all items concerned are promoted to the highest common type. So for example if you multiply an int by a char, the char is first promoted to an int and then the multiplication is carried out. (This is why you only need to explicitly cast one variable to a double - the compiler will then automatically promote all others to double.) In your example, the largest type involved is a 32 bit int, (even the long type) so this is what would be used for the calculations. If this gives a numeric overflow, a standard C compiler just ignores it. As the function you are using takes a double parameter anyway, the final result of the integer calculations will be converted to a double, but only after the integer arithmetic has been carried out. The correct solution is to cast either l1 or i1 to a double first.

 

(Note: there is some ambiguity in the ANSI specification about how many parameters are promoted in this way. Some interpretations are that all parameters in an expression are converted before any calculations are performed, other interpetations are that only the two components of a single operation are matched. So, in your example it would be unwise to just cast l2 to a double - it may work, but it is not guaranteed to be portable between compilers.)

 

JR

Message 3 of 5
(3,424 Views)

Ah, I see my mistake - long int is still 32 bit... Thanks a lot!

0 Kudos
Message 4 of 5
(3,418 Views)

Hi all,

 

the compiler always reuses the memory of the largest representation. In your case the division is between signed longs, so the result is a signed long. This is just general in integer math. How should the c compiler allocate memory for a float automatically?

 

If you convert your variables to float before calculating, everything works.

 

BTW: Same behaviour in LabVIEW

snippet_LV2010.png

 

 

Best Regards,

Andreas Stark
LabVIEW Lead @ Rocket Factory Augsburg
0 Kudos
Message 5 of 5
(3,415 Views)