如何为浮点选择epsilon值?

Dmi*_*ruk 6 math floating-point precision epsilon

由于我们知道0.1 + 0.2 != 0.3由于代表数量有限,我们需要检查帽子abs(0.1+0.2 - 0.3) < ?.问题是,我们通常应该为不同类型选择什么ε值?是否可以根据位数以及可能执行的操作的数量和类型来估计它?

com*_*orm 8

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);
Run Code Online (Sandbox Code Playgroud)

作为一个更完整的例子,比较双打的功能:

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

在实践中,您应该使用的实际epsilon值取决于您正在做什么,以及您实际需要什么样的容差.数值算法通常具有精确容差(平均值和最大值)以及时间和空间估计值.但是精确度估计通常从类似的开始characteristic_value * epsilon.


Ale*_*lex 6

您使用下面的算法估计机器epsilon.您需要将此epsilon乘以1+的整数值(log(number)/ log(2)).在为等式中的所有数字确定此值后,可以使用误差分析来估计特定计算的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)
Run Code Online (Sandbox Code Playgroud)

在您的评论之后,我在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));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)