Sunday, May 17, 2015

Uh oh...

I ran across an interesting little anomaly today.  Consider the following Arduino code which prints the result of dividing an unsigned long by a float.

void setup() 
{
  Serial.begin(115200);
  
  uint32_t f = 10000005UL;

  for (int i = 0; i < 10; i++)
  {
    Serial.print(f);
    Serial.print(" - ");
    Serial.println(f/1e6, 6);
    f--;
  }
}

void loop()
{

}

Unfortunately, the following is the output:

10000005 - 10.000005
10000004 - 10.000004
10000003 - 10.000003
10000002 - 10.000002
10000001 - 10.000001
10000000 - 10.000000
9999999  - 10.000000
9999998  - 9.999999
9999997  - 9.999998
9999996  - 9.999997

I guess I am going to have to look into the Print class a bit and see if the error is in the divide operation or the print operation.  Heads up...

2 comments:

  1. That looks like expected rounding error. Since floats use binary internally, fractions that aren't exactly sums of powers of 2 are rounded. A float has 23 bits in the mantissa, which is smaller than the quantities you are expressing, so I'm sure it's round-off error. Doubles may solve the problem if the compiler has real doubles, but in general this is one of the reasons to not se floating point math in embedded or financial code.

    ReplyDelete
  2. Agreed. I have confirmed it is a rounding error. I was unsure of the number of bits in the floating point mantissa. Thanks for the confirmation!

    ReplyDelete