01-11-2011 12:27 PM
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
Thanks!
Solved! Go to Solution.
01-11-2011 04:58 PM
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;
01-12-2011 04:31 AM
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
01-12-2011 05:56 AM
Ah, I see my mistake - long int is still 32 bit... Thanks a lot!
01-12-2011 06:08 AM - edited 01-12-2011 06:08 AM
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
Best Regards,