简体   繁体   中英

Comparison of floating point numbers in Java

Lets say, I have the following:

float x= ...
float y = ...

What I like to do is just compare them whether x is greater than y or not. I am not interested in their equality.

My question is, should I take into account precision when just performing a > or a < check on floating point values? Am I correct to assume that precision is only taken into account for equality checks?

Since you already have two floats, named x and y, and if there hasn't been any casting before, you can easily use ">" and "<" for comparison. However, let's say if you had two doubles d1 and d2 with d1 > d2 and you cast them to f1 and f2, respectively, you might get f1 == f2 because of precision problems.

There is already a wheel you don't need to invent:

if (Float.compare(x, y) < 0)
    // x is less than y

All float values have the same precision as each other.

It really depends on where those two floats came from. If there was roundoff earlier in their computation, then if the accumulated roundoff is large enough to exceed the difference between the "ideal" answers, you may not get the results you expect for any of the comparison values.

As a general rule, any comparison of floats must be considered fuzzy. If you must do it, you are responsible for understanding the sources of roundoff error and deciding whether you care about it and how you want to handle it if so. It's usually better to avoid comparing floats entirely unless your algorithm absolutely requires that you do so... and if you must, to make sure that a "close but not quite" comparison will not break your program. You may be able to restructure the formulas and order of computation to reduce loss of precision. Going up to double will reduce the accumulated error but is not a complete solution.

If you must compare, and the comparison is important, don't use floats. If you need absolute precision of floating-like numbers, use an infinite-precision math package like bignums or a rational-numbers implementation and accept the performance cost. Or switch to scaled integers -- which also round off, but round off in a way that makes more sense to humans.

This is a difficult question. The answer really depends on how you got those numbers.


First, you need to understand that floating point numbers ARE precise, but that they don't necessarily represent the number that you thought they did. Floating point types in typical programming language represent a finite subset of the infinite set of Real numbers. So if you have an arbitrary real number the chances are that you cannot represent it precisely using a float or double type. In fact ...

The only Real numbers that can be represented exactly as float or double values have the form

  mantissa * power(2, exponent) 

where "mantissa" and "exponent" are integers in prescribed ranges.

And the corollary is that most "decimal" numbers don't have an exact float or double representation either.

So in fact, we end up with something like this:

 true_value = floating_point_value + delta,

where "delta" is the error; ie the small (or not so small) difference between the true value and the float or double value.


Next, when you perform a calculation using floating point values, there are cases where the exact result cannot be represented as a floating point value. An obvious example is:

1.0f / 3.0f 

for which the true value is 0.33333... recurring, which is not representable in any finite base 2 (or base 10!) floating point representation. Instead what happens is that a result is produced by rounding to the nearest float or double value ... introducing more error.

As you perform more and more calculations, the errors can potentially grow ... or stay stable ... depending on the sequence of operations that are performed. (There's a branch of mathematics that deals with this: Numerical Analysis.)


So back to your questions:

"Should I take into account precision when just performing a > or a < check on floating point values?"

It depends on how you got those floating point values, and what you know about the "delta" values relative to the true Real values they nominally represent.

  • If there are no errors (ie delta < the smallest representable difference for the value), then you can safely compare using == , < or > .

  • If there are possible errors, then you need to take account of those errors ... if the semantic of the comparison are intended to couched in terms of the (nominal) true values. Furthermore, you need to have a credible estimate of the "delta" (the accumulated error) when you code the comparison.

In short, there is no simple (correct) answer ...

"Am I correct to assume that precision is only taken into account for equality checks? "

In fact precision is not "taken into account" in any of the comparison operators. These operators treat the operands as precise values, and compare them accordingly. It is up to your code to take account of precision issues, based on your error estimates for the preceding calculations.


If you have estimates for the deltas, then a mathematically sound < comparison would be something like this:

// Assume true_v1 = v1 +- delta_v1 ... (delta_v1 is a non-negative constant)

if (v1 + delta_v1 < v2 - delta_v2) {
    // true_v1 is less than true_v2
}

and so on ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM