由于代码数量有限,我们知道 [df setLocale:[NSLocale systemLocale]];
,因此我们需要检查0.1 + 0.2 != 0.3
。问题是,我们通常应该为不同类型选择什么ε值?是否可以根据位数以及可能执行的操作的数量和类型来估计它?
答案 0 :(得分:6)
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值取决于您正在做什么,以及您实际需要什么样的容差。数值算法通常具有精确容差(平均值和最大值)以及时间和空间估计值。但是精确估计通常从characteristic_value * epsilon
开始。
答案 1 :(得分:5)
您使用下面的算法估算机器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));
}
}
}
答案 2 :(得分:1)
我知道以下精确浮点谓词计算方法:使用标准浮点类型计算值,并计算错误。通常,谓词可以表示为p(x) == 0
或p(x) < 0
等。如果p(x)
的绝对值大于错误,则计算被认为是精确的。否则,使用基于区间的或精确的有理算术。
可以从使用的表达式估计误差。我听说过这种自动发生器,但没有找到任何参考。
据我所知,精确计算主要用于几何,谷歌搜索&#34;精确几何计算&#34;在这个主题上给出了很多。
Here is an article以某种方式解释错误估计。