This very small float constant is more approximate than one might expect.
public class Exponents {
public static void main(String[] args) {
float expFloat = 1.38e-43f; // 1.38 here
System.out.println(expFloat);
}
}
Output:
1.37E-43
This is madness. The output should be 1.38, other outputs are working fine. 1.39 shows 1.39, 1.37 shows 1.37, but 1.38 shows 1.37 --- I mean why is this possible?
A bit more experimenting shows --- 1.47 shows 1.47, 1.49 shows 1.49, but 1.48 shows 1.49. Also, 1.58 shows 1.58, but 1.59 shows 1.58.
source to share
Your number is close to the minimum number expressed as float
. More precisely, it is in the "denormalized" range, so we are limited in accuracy.
1.37e-43f
and 1.38e-43f
are expressed as 0x00000062
in memory. According to the definition of IEEE 754 floats, this means that
- sign is 0 (1 bit), so +
- exponent 0 (8 bits), thus denormalized and
- mantissa is 0x62 (23 bits) which means 0.000 0000 0000 0000 0110 0010
All this means that we have a number
(binary) 0.000 0000 0000 0000 0110 0010 * 2 ^ -126
= 0.1100010 * 2 ^ -142
= 1100010 * 2 ^ -149
= (decimal) 98 * 2 ** -149 = 1.3732724950383207e-43
= (binary) 1.100010 * 2 ^ -143 = (hexadecimal) 0x1.88p-143, as used by the C format specifier %a.
As you can see, only the least significant bits in the mantissa are used.
The least significant bit is 2 ** -149 = 1.401298464324817e-45. It is also a step between accurately represented values.
So,
- the float presented
0x00000062
has, as you can see, the value f2: = 1.3732724950383207e-43 = 0x1.88p-143, - the float presented
0x00000063
is f3: = 1.3872854796815689e-43 = 0x1.8cp-143, - The float presented
0x00000061
is f1: = 1.3592595103950726e-43 = 0x1.84p-143.
There are no possible values in between as we are denormalized and close to the limit of precision.
From the considered values
- 1.36E-43 is closest to f1,
- 1.37E-43 is closest to f2,
- 1.38E-43 is closest to f2 and
- 1.39E-43 is closest to f3.
The same is true for the range 1.47E-43 to 1.49E-43 and 1.57E-43 to 1.59E-43.
source to share
The smallest positive float value ( Float.MIN_VALUE
) is around 1.4E-45, which means that the last digit "x" in 1.3xE-43 goes in "jumps" 1.4 and some digits will be "skipped". "
Floating point numbers are represented in binary, not decimal, and most decimal numbers simply do not have an exact representation. For example, 0.1 has no precise representation. If you work close to the limits of what can be represented, this fact becomes even more obvious.
source to share