0

I know that the range of integers that can be correctly compared is -(2^53 - 1) to 2^53 - 1.

But what is the range of floating point numbers?

// Should the double type conform to this specification? I guess
double c = 9007199254740990.9;
double d = 9007199254740990.8;
System.out.println(c > d); // return false
user15163984
  • 459
  • 2
  • 8
  • https://stackoverflow.com/questions/588004/is-floating-point-math-broken – OldProgrammer Jul 01 '22 at 02:09
  • 1
    "I know that the range of integers that can be correctly compared is -(2^53 - 1) to 2^53 - 1": no you don't. That's the range for the mantissa of a `double`. The range for integers is -(2^31-1) to 2^31-1, and for `long` it is -(2^63-1) to 2^63-1. – user207421 Jul 01 '22 at 02:16
  • @user207421 Thx! The 'double' type range of integers he can put is [-(2^31-1), (2^31-1)]. – user15163984 Jul 01 '22 at 02:29
  • No it isn't. "`double` type range of integers" is a contradiction in terms. Who "he" might be is another mystery, as is what he is putting, and where. – user207421 Jul 01 '22 at 02:29
  • @OldProgrammer I understand that floating-point numbers will have some strange phenomena in the process of addition, but will it be possible to compare sizes? – user15163984 Jul 01 '22 at 02:32
  • What do you mean by 'compare sizes'? – user207421 Jul 01 '22 at 03:57
  • Nit: you and answers assume IEEE-754. Formally Java 1.2 through 16 only guarantees IEEE if your code specifies `strictfp`, but in practice all implementations for a long time have provided it 'optionally'. – dave_thompson_085 Jul 01 '22 at 04:35
  • @dave_thompson_085 Java guarantees IEEE-754 *representation* in all versions. `strictfp` gives you the IEEE-74 semantics. – user207421 Jul 01 '22 at 04:45

3 Answers3

5

There's no particular range in which floating point numbers are guaranteed to be compared correctly - that would require the existence of infinitely many double representations.

All double numbers are accurate to 53 significant figures of their representations in binary. If two numbers differ only in the 54th significant binary figure, they'll generally have the same double representation, unless rounding makes them different.

Dawood ibn Kareem
  • 77,785
  • 15
  • 98
  • 110
  • Do you mean that only the first 53 significant figures will be judged during comparison?(Even if it exceeds 53 bits) – user15163984 Jul 01 '22 at 02:34
  • 1
    Yes. How else could it work? – Louis Wasserman Jul 01 '22 at 03:40
  • 2
    @user15163984 It *can't* exceed 53 bits. There only *are* 53 bits, so talking about the '*first*' 53 bits is meaningless. Your question doesn't make sense. – user207421 Jul 01 '22 at 03:42
  • 1
    Only the first 53 significant binary figures are even stored in the `double`. So most real numbers are not exactly represented by `double` values at all. You'd kind of expect this, since there are infinitely many real numbers, and only finitely many possible `double` values. – Dawood ibn Kareem Jul 01 '22 at 03:59
4

This question seems to be based on a fundamental misunderstanding of (mathematical) Real numbers, and their relationship to IEEE-754.

"Floating point" refers to a representation scheme for Real numbers. Historically that comprises decimal digits and a "decimal point". There are an infinite number of Real numbers, and (correspondingly) an infinite number of floating point numbers. Provided that you have enough paper to write them down.

One property of Real numbers is that there is an infinite number of Real numbers between any pair of distinct Real numbers. That includes any pair that are really close to one another.

IEEE-754 floating point numbers are different. Each one represents a single precise Real number. There is a set of (less than) 2^64 of these Real numbers for IEEE-754 double precision. Any other Real number that is not in that set cannot be precisely represented as a double.

In Java, when we write this:

double c = 9007199254740990.9;
double d = 9007199254740990.8;
System.out.println(c > d); // return false

the value of c will be the IEEE-754 representation that is closest to the real number that the floating point notation denotes. Likewise d. It is not going to be exactly equal to the Real number. (It can only be exact for a finite subset of the infinite set of Real numbers ...)

The print statement illustrates this. The closest IEEE-754 representations for those 2 Real numbers are the same.

What actually happens is that the Java compiler works out what 9007199254740990.9 and 9007199254740990.8 mean as Real numbers. Then it silently rounds those numbers to the nearest IEEE-754 double.


So to your question:

What is the range in which IEEE-754 can correctly compare the size of floating point numbers

A: There is no such range.

If you give me any Real number "x" (expressed in floating point form) that maps to a double value d, I can write you a different Real number "y" (in floating point form) that also maps to the same value d. All I need to do is to add some additional digits to the least significant end of "x".

Note: the reasoning is independent of the actual representation of IEEE-754. It only depends on the fact that IEEE-754 representations have a fixed number of bits. That means that the set of possible values is bounded ... and the rest is a logical consequence of that.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
1

Let's think about the actual bit representation of these double numbers:

We can use System.out.println(Long.toBinaryString(Double.doubleToRawLongBits(c))); to print the bit representation.

Both 9007199254740990.9 and 9007199254740990.8 has the same bit representation following IEEE 754:

0 10000110011 1111111111111111111111111111111111111111111111111111

s(sign) = 0
exp = 10000110011 (binary value, which equals 1075 in decimal)
frac = 111...111 (52 bits)

The precise value of this representation is:

value calculation

With IEEE 754, starting from 2^53, the double type is no longer able to precisely represent all integers larger than 2 ^ 53, let alone floating point numbers.

Regarding the OP question, as mentioned in other answers, there's not an accurate range. For example, the following statement will evaluate as true. We won't say that the range of floating numbers that double can compare is less than 1.1. Generally speaking, the larger the number is, the less precise the double type could represent.

double x1 = 1.1;
double x2 = 1.1000000000000001;
System.out.println(x1 == x2); // true
Haoliang
  • 1,184
  • 4
  • 11