Why does Arduino round off some integers but not others when my desktop PC does not do this? I am writing (in C) some low level digit manipulation routines that convert int to float and vice versa for Arduino. I came across some puzzling behaviour with Arduino rounding some numbers but not others. So I located and extracted the offending code into a simple program which I compiled on desktop Linux PC with GCC and on Arduino - they give different results. Why?
Here are the programs. The goal is to take the float number 1.3140 and the float number 2.3140 and split them into two integers. In the first case I expect '1' and '3140' and in the second case I expect '2' and '3140' (the terminal '0' is important for my application).
The Arduino code:
void setup() {
double dnum,x,y;
uint16_t intpart,fracpart;

Serial.begin(9600);

dnum = 1.3140;

 x=modf(dnum,&amp;y);
 intpart = (uint16_t)y;
 fracpart = (uint16_t)(10000.0*x);

Serial.println(dnum,4);
Serial.println(intpart);
Serial.println(fracpart);

}

and the output I get is:
1.3140
1
3140

Fantastic! Success. But hold on. If I change the hard-coded number to dnum = 2.3140 I get this:
2.3140
2
3139

What? Why did it round the second part down? Am I doing something fundamentally wrong? So I wrote a little C program for my PC (compiled with gcc). Here is the code:
#include&lt;stdint.h&gt;
#include&lt;stdio.h&gt;
#include&lt;math.h&gt;

  
int main (int argc, char *argv[])
{
 double dnum,x,y;
 uint16_t intpart,fracpart;

 dnum = 2.3140;
 
  x=modf(dnum,&amp;y);
  intpart = (uint16_t)y;
  fracpart = (uint16_t)(10000.0*x);
 
 printf(&quot;Int_part = %u\nFrac_Part = %u\n&quot;,intpart,fracpart);
 
 
 return 0;
}

When run I get this result:
Int_part = 2
Frac_Part = 3140

Now that's what I expect - and to be thorough I also did the above C program with dnum = 1.3140; and I again got the 'correct' expected result:
Int_part = 1
Frac_Part = 3140

So why does the Arduino round the fractional part down when I convert it to an integer sometimes and not others?
I tried this on a genuine Arduino Uno, a clone Arduino uno and a clone Arduino nano and all give the same results. In 'theory' it could be some difference in the compiler tolerance to some coding impropriety I have done (gcc is more tolerant) but can anyone tell me what I did wrong and how to get the Arduino to behave (the way I want it to)? Thanks.
When you cast a floating point number to an integer, it always gets
rounded towards zero. If you want round-to-nearest behavior, you should
use the Arduino round() function.
As to the origin of the discrepancy you see, it comes from two facts:

The numbers you use are not exactly representable as floating point
numbers.
The double on an Arduino Uno is actually equivalent to a float
(32 bits only).

When you write a statement such as dnum = 1.3140;, the compiler stores
in dnum the floating point number that is closest to the decimal
number 1.3140.
Compare:
float32(1.3140) = 1.31400001049041748046875
float64(1.3140) = 1.31400000000000005684341886080801486968994140625
float32(2.3140) = 2.3139998912811279296875
float64(2.3140) = 2.31400000000000005684341886080801486968994140625

Out of these 4 examples, only float32(2.3140) is rounded down.