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.

+3


source to share


2 answers


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.

+24


source


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.

+10


source







All Articles