简体   繁体   English

Java中浮点数的比较

[英]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. 我想做的就是比较它们是否x大于y。 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. 由于您已经有两个浮点数,分别命名为x和y,并且如果以前没有任何类型转换,则可以轻松地使用“>”和“ <”进行比较。 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. 但是,假设您有两个d1> d2的双精度数d1和d2,并将它们分别转换为f1和f2,则由于精度问题,可能会得到f1 == f2。

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. 所有float值都具有相同的精度。

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. 如果您需要像浮点数这样的绝对精度,请使用像bignums这样的无穷大数学包或有理数实现,并接受性能成本。 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. 因此,如果您有一个任意的实数,则很可能无法使用float型或double float型精确表示它。 In fact ... 事实上 ...

The only Real numbers that can be represented exactly as float or double values have the form 可以完全一样来表示的唯一实数floatdouble值具有形式

  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. 结果是,大多数“十进制”数字也没有精确的floatdouble float表示形式。

So in fact, we end up with something like this: 因此,实际上,我们最终得到这样的结果:

 true_value = floating_point_value + delta,

where "delta" is the error; 其中“ delta”是错误; ie the small (or not so small) difference between the true value and the float or double value. 即,真实值与floatdouble float值之间的差异很小(或不太小)。


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. 其真实值是0.33333 ...重复出现,在任何有限的基数2(或基数10!)浮点表示中都无法表示。 Instead what happens is that a result is produced by rounding to the nearest float or double value ... introducing more error. 相反,发生的结果是通过四舍五入到最接近的floatdouble值产生了结果...引入了更多错误。

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. 这取决于您如何获得这些浮点值,以及相对于它们名义上表示的真实Real值的“增量”值的了解。

  • If there are no errors (ie delta < the smallest representable difference for the value), then you can safely compare using == , < or > . 如果没有错误(即delta <值的最小可表示差异),则可以使用==<>安全地进行比较。

  • 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 ... 等等 ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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