Andrei Cristian - 2 months ago 6
C Question

# C casting double ->long -> short (using right shift ">>")

I have a small code which does some number transformations. I want to turn a number from double to long and then using right bit shift to cast it to short. But it gives me different results and I don't know why.

I have 3 numbers in an array and I make the sum of them using a

`for`
loop and every time I am gonna cast the result to
`short`
.

There is a number with
`.000000007`
more exactly
`63897600.000000007`
. Adding this to the total and then subtracting it gives me different results.

I can't figure out why does this occur and how can I manage this particular case.

Here is my code:

``````#include <stdio.h>

#define DOUBLETOLONG(number)   (long)(number)
#define NEAREST(number)        ((short)((number + 32768) >> 16))
#define LONGTOSHORT(number)    NEAREST(DOUBLETOLONG(number))

int main() {
int k = 0;
double array[3] ={ 41451520.000000, 63897600.000000007, -63897600.000000007 };
double total_x = array[0];
short j = LONGTOSHORT(total_x);

printf("j = %d\n", j);

for (k = 1; k < 3; k++) {
total_x = total_x+array[k];
j = LONGTOSHORT(total_x);
printf("j = %d\n", j);
}
return 0;
}
``````

This are the results:

``````j = 633
j = 1608
j = 632
``````

## 41451520 + 63897600 = 105349120

In a `double` this integer can still be accurately represented. However, we didn't account for the fractional part `0.000000007`. Let's check what the next biggest `double` is:

``````#include <stdio.h>
#include <math.h>

int main(int argc, char** argv) {
printf("%.23f\n", nextafter(105349120.0, INFINITY));
return 0;
}
``````

Turns out, it's `105349120.000000014901...`. Let's put those next to eachother:

``````105349120.000000014901...
0.000000007
``````

This means that `105349120.000000007` is closer to `105349120` than the next bigger `double`, so it correctly gets rounded down to `105349120`.

However, when we subtract again, `105349120 - 63897600.000000007` gets rounded down, because the next smaller double than `41451520` is (`nextafter(41451520.0, 0)`) `41451519.999999992549...`. Put them next to eachother:

``````41451519.999999992549...
41451519.999999993
``````

Yep, closer to the first double below `41451520` than `41451520` itself. So it correctly gets rounded down to `41451519.999999992549...`.

When you convert `41451519.999999992549...` to an integer it floors the number, resulting in one less than what you expect.

Floating point math is full of surprises. You should read What Every Computer Scientist Should Know About Floating-Point Arithmetic, but perhaps it's still too advanced for now. But it's important to be aware that yes, floating point is full of surprises, but no it isn't magic, and you can learn the pitfalls.