Python ‘floats’ use double
precision 52 bit mantissas:
> (1/3).hex()
‘0x1.5555555555555p-2’ # 13 5’s, 13*4==52
This is 1/3 in binary:
1/3 == 0.0101010101...
52 is an even number and therefore the mantissa(part after the first 1) stored is
010101...
in 52 bits, so ends in ...0101
. So the ieee 754 rounding does not change the 52 bit mantissa, and multyplying by 3 , or binary 11
, gives 0.11111...
which rounds to 1
. Therefore
1.0 / 3.0 * 3.0 == 1.0
in ieee 754, and therefore in python and c++ double
s as pointed out by @Dietrich.
The following code allows to explore the story for float
s which have 23 bits (on my system), which is an odd number...
Note that the rounding to 23 bits gets back to 1, but the automatic promotion from float
to double
in statements like 3.0 * x == 1
will prevent the rounding back to 1.
include <iostream> using namespace std;
int main() {
float x = 1./3, y;
cout << hexfloat;
cout << x << endl; // 1./3. ieee rounded to 23 bits
cout << x * 3.0 << endl; // that times 3.0 exact, ie, promoted to double
cout << (double)x * 3. << endl; // same
cout << x * (float)3.0 << endl; // remains 23 bits, rounded to 1
y = 3.0 * x; // 0x1.0000008p+0 static_cast to 23 bit float
cout << y << endl; // again yields 1
cout << boolalpha; // Now in terms of equalities:
cout << (3.0*x==1.) << endl;
cout << ((float)3.*x==1.) << endl;
cout << (y==1.); return 0;
}
yields
0x1.555556p-2 // rounded to 1.0101...01011
0x1.0000008p+0 // that times 3.0
0x1.0000008p+0
0x1p+0 // now rounds to 1.00...
0x1p+0
false
true
true
Excercise: Explore 49.0. :)