Reputation: 83
I was wondering what largest odd integer that can be represented exactly as a float? And why there is a difference between the largest even integer represented as a float in this case.
I believe it would have to do with the base 2 exponents 2^n-1, however I am not familiar enough with data representation in C to see the distinction.
Upvotes: 4
Views: 3816
Reputation: 222734
For IEEE-754 basic 32-bit binary floating-point, the largest representable odd integer is 224−1.
For IEEE-754 basic 64-bit binary floating-point, the largest representable odd integer is 253−1.
This is due to the fact that the formats have 24-bit and 53-bit significands. (The significand is the fraction part of a floating-point number.)
The values represented by the bits in the significand are scaled according to the exponent of the floating-point number. In order to represent an odd number, the floating-point number must have a bit in the significand that represents 20. With a 24-bit significand, if the lowest bit represents 20, then the highest bit represents 223. The largest value is obtained when all the bits are on, which makes the value 20 + 21 + 22 + … 223, which equals 224−1.
More generally, the largest representable odd integer is normally scalbnf(1, FLT_MANT_DIG) - 1
. This can also be computed as (2 - FLT_EPSILON) / FLT_EPSILON
. (This assumes a normal case in which FLT_RADIX
is even and FLT_MANT_DIG <= FLT_MAX_EXP
. Note that if FLT_MANT_DIG == FLT_MAX_EXP
, the latter expression, with FLT_EPSILON
, should be used, because the former overflows.)
The abnormal cases, just for completeness:
FLT_RADIX
is odd and FLT_MANT_DIG <= FLT_MAX_EXP
, the largest representable odd integer is FLT_MAX
if FLT_MANT_DIG
is odd and FLT_MAX - scalbnf(FLT_EPSILON, FLT_MAX_EXP+1)
otherwise.FLT_RADIX
is even and FLT_MANT_DIG > FLT_MAX_EXP
, then: If FLT_MAX_EXP > 0
, the largest representable odd integer is floorf(FLT_MAX)
. Otherwise, no odd integers are representable.FLT_RADIX
is odd and FLT_MANT_DIG > FLT_MAX_EXP
, then: If FLT_MAX_EXP > 0
, the largest representable odd integer is floorf(FLT_MAX)
if FLT_MANT_DIG - FLT_MAX_EXP
is odd or floorf(FLT_MAX)-1
otherwise. Otherwise, no odd integers are representable.Upvotes: 9
Reputation: 7748
The largest odd integer representable as a 32-bit float is 2^24 - 1.
More specifically, a 32-bit float can exactly represent the following integers:
In other words, here are the integers exactly representable:
0
1
2
...
16777215
16777216 (= 2^24)
16777218
16777220
...
33554430
33554432 (= 2^25)
33554436
33554440
...
67108860
67108864 (= 2^26)
67108872
67108880
...
Note that this applies both for positive and negative integers, for example, all negative integers down to -2^24 can be exactly represented.
Below is some C++ code doing integers-to-float conversions for integers around 2^24, around 2^25, and around 2^26, to see this in practice.
#include <iostream>
#include <iomanip>
#include <vector>
int main()
{
int _2pow24 = 1 << 24;
int _2pow25 = 1 << 25;
int _2pow26 = 1 << 26;
std::cout << "2^24 = " << _2pow24 << std::endl;
std::cout << "2^25 = " << _2pow25 << std::endl;
std::cout << "2^26 = " << _2pow26 << std::endl;
std::vector<int> v;
for (int i = -4; i < 4; ++i) v.push_back(_2pow24 + i);
for (int i = -8; i < 8; ++i) v.push_back(_2pow25 + i);
for (int i = -16; i < 16; ++i) v.push_back(_2pow26 + i);
for (int i : v) {
std::cout << i << " -> "
<< std::fixed << std::setprecision(1)
<< static_cast<float>(i)
<< std::endl;
}
return 0;
}
Output:
2^24 = 16777216
2^25 = 33554432
2^26 = 67108864
16777212 -> 16777212.0
16777213 -> 16777213.0
16777214 -> 16777214.0
16777215 -> 16777215.0
16777216 -> 16777216.0
16777217 -> 16777216.0
16777218 -> 16777218.0
16777219 -> 16777220.0
33554424 -> 33554424.0
33554425 -> 33554424.0
33554426 -> 33554426.0
33554427 -> 33554428.0
33554428 -> 33554428.0
33554429 -> 33554428.0
33554430 -> 33554430.0
33554431 -> 33554432.0
33554432 -> 33554432.0
33554433 -> 33554432.0
33554434 -> 33554432.0
33554435 -> 33554436.0
33554436 -> 33554436.0
33554437 -> 33554436.0
33554438 -> 33554440.0
33554439 -> 33554440.0
67108848 -> 67108848.0
67108849 -> 67108848.0
67108850 -> 67108848.0
67108851 -> 67108852.0
67108852 -> 67108852.0
67108853 -> 67108852.0
67108854 -> 67108856.0
67108855 -> 67108856.0
67108856 -> 67108856.0
67108857 -> 67108856.0
67108858 -> 67108856.0
67108859 -> 67108860.0
67108860 -> 67108860.0
67108861 -> 67108860.0
67108862 -> 67108864.0
67108863 -> 67108864.0
67108864 -> 67108864.0
67108865 -> 67108864.0
67108866 -> 67108864.0
67108867 -> 67108864.0
67108868 -> 67108864.0
67108869 -> 67108872.0
67108870 -> 67108872.0
67108871 -> 67108872.0
67108872 -> 67108872.0
67108873 -> 67108872.0
67108874 -> 67108872.0
67108875 -> 67108872.0
67108876 -> 67108880.0
67108877 -> 67108880.0
67108878 -> 67108880.0
67108879 -> 67108880.0
Upvotes: 4