# cast double to long leads to unexpected results

I wrote a little program to show my problem:

``````void setup()
{
Serial.begin(9600);

double K=39.85;
double a=K*100;
Serial.print("a= ");
Serial.println(a);

long val_long = 0;
val_long = a;
Serial.print("val_long= ");
Serial.println(val_long);
}

void loop() {
}
``````

I get this back from my Arduino uno:

``````a= 3985.00
val_long=3984
``````

I've been pondering for a long time and can't find the mistake! Why is the long value decremented by one? Can anybody help me please?

• upvote for uncluding minimal sketch Jan 7 '20 at 0:44

The problem is that float numbers are seldom an exact representation. So the float is stored as the closest number that is exactly representable as a float, namely
10446438 × 2−18 = 39.84999847412109375.

When you multiply this by 100, you get 16322559 × 2−12 = 3984.999755859375.

And than casting to an int or long results in 3984, not 3985.

so whenever you cast a value from a float or double to an int or long, you always should add 0.5 (so all values from [x - 0.5, x + 0.5) are rounded to x assuming x >= 0, thus:

``````val_long = int(a + 0.5);
``````

Beware of negative values, see therefore https://www.cs.cmu.edu/~rbd/papers/cmj-float-to-int.html

Better is to use the `round` function, see comment of Edgar Bonet below.

UPDATE

See comment of Lightness Races with Monica

In case it's not wanted to round up, but you still want 39.84999847412109375 to be 39.85, than you have to add a value that has the value of the least significant bit (actually slightly less but that is impossible to define). In most cases, it's best to add half the significance you want. So if you need two decimal accuracy, add 0.005.

• Thank you so much, you made my day! Now everything works fine. Jan 6 '20 at 23:23
• `Serial.println(a,5);` might have revealed that issue already. Especially on 8bit Arduinos with `double` being only 32 bit wide. (Same as float) Jan 7 '20 at 0:00
• 1. I edited the answer to add the exact numbers. 2. You can use `round()`, from the Arduino core. It's a macro that adds ±0.5 (depending on the sign) before casting to long. Jan 7 '20 at 9:19
• @EdgarBonet Thank you very much. I will also add in my answer a note to your comment. Jan 7 '20 at 9:26
• @MichelKeijzers If `K` is 39.856 then `a` is 3985.6, so program's output is 3985, which is presumably deliberate. Your suggestion changes the output to 3986. You've changed the meaning of the program without mentioning it. An alternative is to use "another workaround for [these] little inaccuracies [like the one causing this bug]", such as epsilons. That being said, if `K` will only ever have max 2 meaningful decimal places, then this is moot. Jan 7 '20 at 16:21