Reputation: 259
Note: I am coding the following in the Arduino variant of C++.
From a given float (always with four decimal digits), I wish to extract just the decimal part ("mantissa") as an integer.
So I attempted this method:
void ExtractDecimalPart(float Value) {
int IntegerPart = (int)(Value);
int DecimalPart = 10000 * (Value - IntegerPart); //10000 b/c my float values always have exactly 4 decimal places
Serial.println (DecimalPart);
}
But the above results in the following:
ExtractDecimalPart (1234.5677); //prints 5677
ExtractDecimalPart (1234.5678); //prints 5677
ExtractDecimalPart (1234.5679); //prints 5678
Note that the latter two print out wrong; I'm guessing this is due to floating point precision issues.
What is an economical way to solve the above?
Upvotes: 1
Views: 9343
Reputation: 41922
32-bit float
has 23 bits of mantissa, so it can hold only about 7 digits of precision. Your example uses 8 digits, so the last one is just "garbage". You must use a higher precision floating-point type (which is double
and long double
in standard C++).
On Arduino depending on the variant you may have a standard compliant 64-bit double
type or not. If double
is exactly the same as float
you have several solutions:
double
math library.
double
is just too costly on an 8-bit MCU like that you can create a custom floating-point type like 40-bit or 48-bit.float-float
arithmetic type like this.You can find out more information regarding fixed-point in this question, or in fixed-point tag
Upvotes: 0
Reputation: 2793
The simplest way to avoid problems with floating point precision is to cast your number to a string and then only print what's after the point.
EDIT
I'm not sure how to do it with arduino's version of c++
so feel free to edit my answer to add an example everyone!
Upvotes: 1
Reputation: 1398
This is a cool question.
I will assume that ardiuno is using IEEE 754 when you set a float equal to 1234.5677 the number closest to that that fits in 4 bytes is 1.2345677490234375E3 which looks like 0x449A522B in hex.
but when you put 1234.5678 in to a float the best number it can form is 1.2345677490234375E3 Which is just short. In hex it is 0x449A522B.
So in short floats just can't store number that require number of digites you are using.
Upvotes: 2