Help with Adding Floats

Hello,

I'm having a devil of a problem here. I'm trying to add two floats and have mixed results.

The Code is as follows:

double first = 7722;
double second = 0.5432;
Serial.println(first, 4);
Serial.println(second, 4);
double total = (first+second);
Serial.println((total), 4);

first = 3828;
second = 0.5432;
Serial.println(first, 4);
Serial.println(second, 4);
total = (first+second);
Serial.println(total, 4);

The output is as follows:

7722.0000
0.5432
7722.5429

3828.0000
0.5432
3828.5432

The first calculation is correct. The second calculation is . . . not.

Any ideas about what's going on?

The first calculation is correct. The second calculation is . . . not.

Any ideas about what's going on?

Looks exactly the opposite to me.

I'd try actually specifying floating point values for first:
double first = 7722.0;

jdog,

It looks to me like you are simply exceeding the number of significant digits that an Arduino floating point number can hold.

Note that for Arduino programming, the 'double' type is exactly the same as the 'float' type. You don't get any more digits by using 'double'.

Regards,

-Mike

Any ideas about what's going on?

Short version:

You try to represent a number that can't be represented precisely with the chosen data type (double). It looks strange but everything is as it should be.

Longer version:

On the AVR-library the type double is 32 bit. Assuming the default IEEE standard representation, those 32 are split the following way:

  • 1 bit for the sign
  • 8 bit for the exponent (range -126 to + 127)
  • 23 bit for the fractional part giving 16777216 possible numbers.

As you can see, the fractional part can only represent 7 digits correctly. If now you enter or calculate a number with more fractional digits, whatever you get will be rounded to the next best representable number. Sometimes that will be correct, sometimes the last digits will be wrong.

More details about this in any textbook about numeric computing or floating point numbers.

Korman

Everyone, thanks for the help! Very informative, I'll try a different approach.

Could this problem be solved by using fixed floats? Is that supported in ARduino?

Fixed floats?
That's an oxymoron - do you mean fixed-point?
Yes, they're supported, but not as distinct data-types, so you have to do your own scaling.

jdog,

it would help to know, what problem you're trying to solve. There are libraries for higher precision math, but those tend to use more resources that you have available on the Arduino. In specific cases alternatives like using different algorithms, using integers, strings or packed BCD might provide a lightweight solution. But without knowing the problem, it's hard to give good advice.

Korman

The application is pretty simple: I'm trying to read serial data from a GPS and turn it into float types. It will be for datalogging and eventually navigation.

For the datalogging, I've run a program to test all the possible numbers and the errors in output I'm currently seeing are acceptable (+/- 0.000018 max, which at the equator is about 5 meters). I'm not sure that that kind of error propagates out to after running Haversine equations (which would be the goal).

Because of the innacuracies inherit in commercial GPS, and my application which is for a wide range of a calculations (basically a robot), I'd like to be as precise as possible with the numbers.

So the numbers I used in the above code were generated by the GPS chip I'm using.

I'm happy to conceded that i may be on the wrong track here (this is my first real project in Arduino). Any thoughts? Does this clear up the situation?

In this case, forget double and floats as they come with the Arduino. It's like doing brain surgery with a hatchet, you'll only be introducing errors.

Whatever calculation you do needs to be aware of the error margin and preserve precision. This is probably just the reason, why the GPS-logger delivers the data as 2 double values. But to cheer you up, the problem has already been solved by others, you don't need to reinvent the wheel.

Korman

Thanks Korman. I appreciate the cheer.

Korman, one more shot. Someone recomended this to me on sourceforge:

Documentation is in here: http://voxel.dl.sourceforge.net/project/avrfix/avrfix/Bachelor_s%20Thesis/avrfix.pdf

But the quick description is:

When applications need sophisticate mathematical operations on microcontrollers which only support integer arithmetics, floating point emulation is often too expensive and unnecessary. A fixed point library features faster operation than floating point emulation while being more accurate than integer arithmetics. This work is especially designated for use with the TTP/A protocol respectively an implementation of it for Atmel 8-bit microcontrollers which needs exclusive access to several registers. Because of that, precompiled libraries which normally would be used, are not sufficient. In this work, we cover general fixed point arithmetics as well as the specific implementation of basic and advanced arithmetic operations in reference to the ISO/IEC paper DTR 18037. Because microcontrollers do not offer huge amounts of neither space nor clock rate, small code size and short runtime is a main concern of this work.

Would that