什么时候比较浮点值是否相等? [英] When is it useful to compare floating-point values for equality?

查看:128
本文介绍了什么时候比较浮点值是否相等?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我似乎看到人们一直在这里问有关比较浮点数的问题。规范的答案永远是:只要看一下数字是否在彼此的小数范围内……

I seem to see people asking all the time around here questions about comparing floating-point numbers. The canonical answer is always: just see if the numbers are within some small number of each other…

所以问题是这样的:为什么你要知道两个浮点数彼此相等?

So the question is this: Why would you ever need to know if two floating point numbers are equal to each other?

在我所有的编码年中,我从不需要这样做(尽管我承认即使 I 也不是无所不知的)。从我的角度来看,如果您出于某种原因试图使用浮点数,并且出于某种原因想知道数字是否相等,则可能应该使用整数类型(或在支持该语言的语言中为十进制类型)。我只是错过了什么吗?

In all my years of coding I have never needed to do this (although I will admit that even I am not omniscient). From my point of view, if you are trying to use floating point numbers for and for some reason want to know if the numbers are equal, you should probably be using an integer type (or a decimal type in languages that support it). Am I just missing something?

推荐答案

比较浮点数是否相等的一些原因是:

A few reasons to compare floating-point numbers for equality are:


  • 测试软件。给定应符合精确规范的软件,精确结果可能是已知的或可以计算的,因此测试程序会将目标软件的结果与预期结果进行比较。

  • 执行精确算术。精心设计的软件可以对浮点数执行精确的算术运算。简单地说,这可能只是整数运算。 (在提供IEEE-754 64位双精度浮点但仅32位整数算术的平台上,可以使用浮点算术执行53位整数算术。)比较执行精确算术时的相等性是

  • 搜索排序或结构化数据。浮点值可以用作搜索的关键字,在这种情况下,必须进行相等性测试才能确定是否找到了所需的项目。 (如果存在NaN,则存在问题,因为它们在任何订单测试中均报告为假。)

  • 避免出现极点和不连续性。函数在某些点上可能具有特殊的行为,其中最明显的是除法。软件可能需要测试这些点并将执行转移到其他方法。

  • Testing software. Given software that should conform to a precise specification, exact results might be known or feasibly computable, so a test program would compare the subject software’s results to the expected results.
  • Performing exact arithmetic. Carefully designed software can perform exact arithmetic with floating-point. At its simplest, this may simply be integer arithmetic. (On platforms which provide IEEE-754 64-bit double-precision floating-point but only 32-bit integer arithmetic, floating-point arithmetic can be used to perform 53-bit integer arithmetic.) Comparing for equality when performing exact arithmetic is the same as comparing for equality with integer operations.
  • Searching sorted or structured data. Floating-point values can be used as keys for searching, in which case testing for equality is necessary to determine that the sought item has been found. (There are issues if NaNs may be present, since they report false for any order test.)
  • Avoiding poles and discontinuities. Functions may have special behaviors at certain points, the most obvious of which is division. Software may need to test for these points and divert execution to alternate methods.

请注意,在使用时,只有这些测试中的最后一个用于相等性浮点算术近似于实数算术。 (此示例列表不完整,因此我不希望这是唯一的此类用法。)前三个是特殊情况。通常,在使用浮点算术时,一种方法是逼近实数算术并使用大多数连续函数。连续函数对于使用浮点算术是好的,因为它们以正常的方式传输错误。例如,如果到目前为止您的计算已经产生了一些 a ',它近似于理想的数学结果 a ,而您有一个 b ',则近似理想的数学结果 b ,则计算出的总和 a '+ b '将近似于 a + b

Note that only the last of these tests for equality when using floating-point arithmetic to approximate real arithmetic. (This list of examples is not complete, so I do not expect this is the only such use.) The first three are special situations. Usually when using floating-point arithmetic, one is approximating real arithmetic and working with mostly continuous functions. Continuous functions are "okay" for working with floating-point arithmetic because they transmit errors in "normal" ways. For example, if your calculations so far have produced some a' that approximates an ideal mathematical result a, and you have a b' that approximates an ideal mathematical result b, then the computed sum a'+b' will approximate a+b.

不连续的函数可能会破坏此行为。例如,如果我们尝试将数字四舍五入到最接近的整数,那么当 a 为3.49时会发生什么?我们的近似值 a '可能是3.48或3.51。计算舍入时,近似值可能会产生3或4,从而将很小的误差变成很大的误差。在浮点算术中使用不连续函数时,必须要小心。例如,考虑评估二次公式(- b ±sqrt( b 2 -4 ac )) /(2 a )。如果在 b 2 -4 ac 的计算过程中出现轻微错误,则结果可能为负,然后为 sqrt 将返回NaN。因此,软件不能简单地使用浮点运算,就好像它很容易近似于实数运算一样。程序员必须了解浮点运算并警惕陷阱,这些问题及其解决方案可能特定于特定的软件和应用程序。

Discontinuous functions, on the other hand, can disrupt this behavior. For example, if we attempt to round a number to the nearest integer, what happens when a is 3.49? Our approximation a' might be 3.48 or 3.51. When the rounding is computed, the approximation may produce 3 or 4, turning a very small error into a very large error. When working with discontinuous functions in floating-point arithmetic, one has to be careful. For example, consider evaluating the quadratic formula, (−b±sqrt(b2−4ac))/(2a). If there is a slight error during the calculations for b2−4ac, the result might be negative, and then sqrt will return NaN. So software cannot simply use floating-point arithmetic as if it easily approximated real arithmetic. The programmer must understand floating-point arithmetic and be wary of the pitfalls, and these issues and their solutions can be specific to the particular software and application.

测试相等性是不连续的功能。它是一个函数f( a b ),除沿 a = b 线外,其他所有地方均为0。由于它是一个不连续的函数,因此可以将小错误变成大错误-如果使用理想数学计算,它可以报告为不相等的相等数;如果使用理想数学计算,它可以报告为相等的不相等数。

Testing for equality is a discontinuous function. It is a function f(a, b) that is 0 everywhere except along the line a=b. Since it is a discontinuous function, it can turn small errors into large errors—it can report as equal numbers that are unequal if computed with ideal mathematics, and it can report as unequal numbers that are equal if computed with ideal mathematics.

使用此视图,我们可以看到相等性测试是一般函数类的成员。它没有平方根或除法的特殊之处,它在大多数地方是连续的,但在某些地方是不连续的,因此必须谨慎对待其使用。我们会为每个应用程序量身定制这种护理。

With this view, we can see testing for equality is a member of a general class of functions. It is not any more special than square root or division—it is continuous in most places but discontinuous in some, and so its use must be treated with care. That care is customized to each application.

我将介绍一个对平等测试非常有用的地方。我们实现了一些数学库例程,这些例程被指定为忠实舍入的。例程的最佳质量是正确舍入。考虑一个函数,其确切的数学结果(对于特定输入 x )为 y 。在某些情况下, y 可以用浮点格式精确表示,在这种情况下,良好的例程将返回 y 。通常, y 不能精确表示。在这种情况下,它位于浮点格式可表示的两个数字之间,其中一些数字 y 0 y 1 。如果例程正确舍入,则返回 y 0 y 1 中的任意一个更接近 y 。 (在出现平局的情况下,它返回的位数甚至更低。此外,我仅在讨论从最近到最近的关系到偶数模式。)

I will relate one place where testing for equality was very useful. We implement some math library routines that are specified to be faithfully rounded. The best quality for a routine is that it is correctly rounded. Consider a function whose exact mathematical result (for a particular input x) is y. In some cases, y is exactly representable in the floating-point format, in which case a good routine will return y. Often, y is not exactly representable. In this case, it is between two numbers representable in the floating-point format, some numbers y0 and y1. If a routine is correctly rounded, it returns whichever of y0 and y1 is closer to y. (In case of a tie, it returns the one with an even low digit. Also, I am discussing only the round-to-nearest ties-to-even mode.)

如果一个例程如实地四舍五入,则可以返回 y 0 y 1

If a routine is faithfully rounded, it is allowed to return either y0 or y1.

现在,这是我们要解决的问题:我们有一些单精度例程版本,例如 sin0 ,我们知道它是忠实的。我们有一个新版本, sin1 ,我们想测试它是否如实地取整。我们拥有可以高精度地评估数学正弦函数的多精度软件,因此我们可以使用它来检查 sin1 的结果是否真实。但是,多精度软件运行缓慢,我们想测试所有40亿个输入。 sin0 sin1 都很快,但是允许 sin1 具有与 sin0 不同的输出,因为 sin1 只需要如实地四舍五入,而不必与 sin0

Now, here is the problem we wanted to solve: We have some version of a single-precision routine, say sin0, that we know is faithfully rounded. We have a new version, sin1, and we want to test whether it is faithfully rounded. We have multiple-precision software that can evaluate the mathematical sin function to great precision, so we can use that to check whether the results of sin1 are faithfully rounded. However, the multiple-precision software is slow, and we want to test all four billion inputs. sin0 and sin1 are both fast, but sin1 is allowed to have outputs different from sin0, because sin1 is only required to be faithfully rounded, not to be the same as sin0.

但是,中的最多 sin1 的结果与 sin0 相同。 (这部分是数学库例程设计方式的结果,在使用一些最终算术运算来传递最终结果之前,使用某种额外的精度来获得非常接近的结果。这往往会得到正确舍入的结果 most 的时间,但有时会滑到下一个最近的值。)因此,我们可以这样做:

However, it happens that most of the sin1 results are the same as sin0. (This is partly a result of how math library routines are designed, using some extra precision to get a very close result before using a few final arithmetic operations to deliver the final result. That tends to get the correctly rounded result most of the time but sometimes slips to the next nearest value.) So what we can do is this:


  • 对于每个输入,计算 sin0 sin1

  • 比较结果是否相等。

  • 如果结果相等,就完成了。如果不是,请使用扩展精度软件测试 sin1 结果是否真实地进行四舍五入。

  • For each input, calculate both sin0 and sin1.
  • Compare the results for equality.
  • If the results are equal, we are done. If they are not, use the extended precision software to test whether the sin1 result is faithfully rounded.

同样,这是使用浮点算法的一种特殊情况。但这是测试平等性很好的一种方法。最终的测试程序将在几分钟而不是几个小时内运行。

Again, this is a special case for using floating-point arithmetic. But it is one where testing for equality serves very well; the final test program runs in a few minutes instead of many hours.

这篇关于什么时候比较浮点值是否相等?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆