Compare Two Float Variables in C++

Comparing Same Float Values In C

While many people will tell you to always compare floating point numbers with an epsilon (and it's usually a good idea, though it should be a percentage of the values being compared rather than a fixed value), that's not actually necessary here since you're using constants.

Your specific problem here is that:

float a = 0.7;

uses the double constant 0.7 to create a single precision number (losing some precision) while:

if (a == 0.7)

will compare two double precision numbers (a is promoted first).

The precision that was lost when turning the double 0.7 into the float a is not regained when promoting a back to a double.

If you change all those 0.7 values to 0.7f (to force float rather than double), or if you just make a a double, it will work fine - I rarely use float nowadays unless I have a massive array of them and need to save space.

You can see this in action with:

#include <stdio.h>
int main (void){
float f = 0.7; // double converted to float
double d1 = 0.7; // double kept as double
double d2 = f; // float converted back to double

printf ("double: %.30f\n", d1);
printf ("double from float: %.30f\n", d2);

return 0;
}

which will output something like (slightly modified to show difference):

double:            0.6999999|99999999955591079014994
double from float: 0.6999999|88079071044921875000000
\_ different beyond here.

Compare two float variables in C++

The output: same although both the float variables hold different values.

"float variables hold different values." is unfounded.

same was printed because values a,b are the same even if the initialization constants differ.


Typical float is 32-bits and can represent about 232 different values such as 1.0, 1024.0, 0.5, 0.125. These values are all of the form: +/- some_integer*2some_integer

1.012345679 and 1.012345678 are not in that float set. @Rudy Velthuis.

1.012345 67165374755859375 // `float` member
1.012345 678
1.012345 679
1.012345 790863037109375 // `float` member

Similar applies for double, yet with more precision - commonly 64 bits.

1.012345679 and 1.012345678 are not in that double set either

1.012345 67799999997106397131574340164661407470703125    // `double` member
1.012345 678
1.012345 6780000001931085762407747097313404083251953125 // `double` member
...
1.012345 6789999998317597373898024670779705047607421875 // `double` member
1.012345 679
1.012345 67900000005380434231483377516269683837890625 // `double` member

It can be thought of as 2 steps of rounding. Code 1.012345679 is rounded to the nearest double 1.01234567900000005380434231483377516269683837890625. Then the assignment rounds the double to the nearest float 1.01234567165374755859375.

float a = 1.012345679;
// 'a' has the value of 1.01234567165374755859375

Likewise for b. Code 1.012345678 is rounded to the nearest double 1.01234567799999997106397131574340164661407470703125. Then the assignment rounds the double to the nearest float 1.01234567165374755859375.

flaot b = 1.012345678;
// 'b' has the value of 1.01234567165374755859375

a and b have the same value.

Comparing float and double in C

The exact value of the closest float to 1.1 is 1.10000002384185791015625. The binary equivalent is 1.00011001100110011001101

The exact value of the closest double to 1.1 is 1.100000000000000088817841970012523233890533447265625. The binary equivalent is 1.0001100110011001100110011001100110011001100110011010.

Lining up the two binary numbers next to each other:

1.00011001100110011001101
1.0001100110011001100110011001100110011001100110011010

The first few truncated bits for rounding to float are 11001100, which is greater than half, so the conversion to float rounded up, making its least significant bits 11001101. That rounding resulted in the most significant difference being a 1 in the float in a bit position that is 0 in the double. The float is greater than the double, regardless of values of bits of lower significance being zero in the float extended to double, but non-zero in the double.

Comparing floating point numbers in C

To determine whether it's close enough to zero that it will print as 0.000000 to six decimal places, something like:

fabs(d) < 0.0000005

Dealing with small inaccuracies in floating-point calculations can get quite complicated in general, though.

If you want a better idea what value you've got, try printing with %g instead of %f.



Related Topics



Leave a reply



Submit