3
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 crazy. The output should be 1.38 , other outputs working fine. 1.39 shows 1.39, 1.37 shows 1.37, but 1.38 shows 1.37 --- I mean just how come is this possible?

A little 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 .

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
KASH J
  • 73
  • 5
  • 15
    everyone knows floating point is crazy until people doesn't consider it crazy anymore. – DnR Oct 24 '14 at 06:34
  • make it double, the number doesn't fit in float – Heisenberg Oct 24 '14 at 06:38
  • Thanks for formatting the question @DnR .. But can you explain me why this happening? – KASH J Oct 24 '14 at 06:38
  • you should thanks to @kocko for that. well, i'm waiting for the explanation too :D – DnR Oct 24 '14 at 06:41
  • oops... sorry, new to stack overflow. Thanks @kocko – KASH J Oct 24 '14 at 06:45
  • 2
    Why are you using float instead of double? Unless you have a very good reason to use float, you should always use double. You are using denormalized numbers, where float loses precision. – gnasher729 Oct 24 '14 at 13:45
  • @KASHJ This site is for asking and answering. You don't need to request that people answer your question: if they could (or wanted to), they would. They already know that they can post an answer if they have something to say, no need to tell them individually with a comment. – Pascal Cuoq Oct 24 '14 at 15:40
  • 1
    Did you try `1.38e-44f`? – Hot Licks Oct 24 '14 at 16:13
  • @HotLicks yes I did try. In 1.38e-44f , the 8 is smaller than FLOAT.MIN_VALUE , so it cant be represented and is completely ignored. – KASH J Oct 24 '14 at 23:35

2 Answers2

24

Your number is close to the minimum number expressible as a float. To be exact, it is in the "denormalized" range, so we are limited in precision.

1.37e-43f and 1.38e-43f are both expressed as 0x00000062 in memory. According to the definition of IEEE 754 floats, that means that

  • the sign is 0 (1 bit), thus +
  • the exponent is 0 (8 bit), thus denormalized and
  • the mantissa is 0x62 (23 bit), meaning 0.000 0000 0000 0000 0110 0010

All this means we have a number of

(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 see, only the lowest bits in the mantissa are used.

The lowest bit has a value of 2 ** -149 = 1.401298464324817e-45. This is as well the step between exactly representable values.

So,

  • the float represented by 0x00000062 has, as seen, a value of f2 := 1.3732724950383207e-43 = 0x1.88p-143,
  • the float represented by 0x00000063 has a value of f3 := 1.3872854796815689e-43 = 0x1.8cp-143,
  • the float represented by 0x00000061 has a value of f1 := 1.3592595103950726e-43 = 0x1.84p-143.

There are no possible values in-between, as we are denormalized and close to the precision limit.

From the values we examine,

  • 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 holds for the range 1.47E-43 to 1.49E-43 and 1.57E-43 to 1.59E-43.

glglgl
  • 89,107
  • 13
  • 149
  • 217
  • It is perhaps worth mentioning the purpose of all this. Dropping normalization, and the leading implicit 1-bit, for the minimum exponent allows very approximate representation of tiny numbers that would otherwise underflow to zero. – Patricia Shanahan Oct 24 '14 at 16:34
  • @PatriciaShanahan That's right, but I just wanted to give a short overview about this subject. The details can be read about at more appropriate places. – glglgl Oct 24 '14 at 18:25
10

The smallest positive float value (Float.MIN_VALUE) is about 1.4E-45, which means that the last digit "x" in 1.3xE-43 goes in "hops" of 1.4, and some numbers will get "skipped."

Floating point numbers are represented in binary, not decimal, and most decimal numbers just don't have an exact representation. For example 0.1 does not have an exact representation. If you work close to the limits of the magnitudes that can be represented this fact becomes even more apparent.

Joni
  • 108,737
  • 14
  • 143
  • 193