如何为浮点数选择 epsilon 值?

How to choose epsilon value for floating point?

由于我们知道 0.1 + 0.2 != 0.3 由于数量有限,我们需要改为检查帽子 abs(0.1+0.2 - 0.3) < ε。问题是,对于不同的类型,我们一般应该选择多少ε值呢?是否可以根据位数和可能执行的操作的数量和类型来估算?

epsilon 的基线值是 1.0 与下一个最高可表示值之间的差值。在 C++ 中,此值可用作 std::numeric_limits<T>::epsilon().

请注意,您至少需要将此值缩放为您正在测试的实际数字的比例。此外,由于精度仅与数值大致成比例,您可能希望将边距增加一个小因子以防止虚假错误:

double epsilon = std::numeric_limits<double>::epsilon();

// C++ literals and math functions are double by default
bool is_near = abs(0.1+0.2 - 0.3) <= 0.3 * (2*epsilon);

作为一个更完整的例子,比较双精度的函数:

bool is_approximately_equal(double a, double b) {
  double scale = max(abs(a), abs(b));
  return abs(a - b) <= scale * (2*epsilon);
}

实际上,您应该使用的实际 epsilon 值取决于您在做什么,以及您实际需要什么样的容差。数值算法通常具有精度公差(平均值和最大值)以及时间和 space 估计值。但精度估计通常以 characteristic_value * epsilon.

之类的开头

您可以使用以下算法估算机器 epsilon。您需要将此 epsilon 乘以 1+(log(number)/log(2)) 的整数值。为方程中的所有数字确定此值后,您可以使用 error analysis 来估计特定计算的 epsilon 值。

epsilon=1.0

while (1.0 + (epsilon/2.0) > 1.0) {
  epsilon = epsilon /2.0     
}
//Calculate error using error analysis for a + b
epsilon_equation=Math.sqrt(2*epsilon*epsilon)

document.write('Epsilon: ' + epsilon_equation+'<br>')
document.write('Floating point error: ' + Math.abs(0.2 + 0.4 -0.6)+'<br>')
document.write('Comparison using epsilon: ')
document.write(Math.abs(0.2 + 0.4 -0.6)<epsilon_equation)

根据您的评论,我在 C# 中尝试了相同的方法,它似乎有效:

using System;

namespace ConsoleApplication
{
   
    public class Program
    {
        public static void Main(string[] args)
        {
            double epsilon = 1.0;

            while (1.0 + (epsilon/2.0) > 1.0)
            {
                epsilon = epsilon/2.0;
            }

            double epsilon_equation = Math.Sqrt(2*epsilon*epsilon);

            Console.WriteLine(Math.Abs(1.0 + 2.0 - 3.0) < Math.Sqrt(3.0 * epsilon_equation * epsilon_equation));
        }
    }
}

我知道以下精确浮点谓词计算方法:使用标准浮点类型计算值,并计算误差。通常,谓词可以表示为p(x) == 0p(x) < 0等。如果p(x)的绝对值大于误差,则认为计算准确。否则,使用基于区间或精确有理算术。

可以根据所使用的表达式来估计误差。我听说过这个自动生成器,但没有找到任何参考。

据我所知,精确计算主要用于几何,谷歌搜索 "exact geometric computations" 给出了很多关于这个主题的信息。

Here is an article 以某种方式解释了误差估计。