Math 如何选择浮点的ε值?

Math 如何选择浮点的ε值?,math,floating-point,precision,epsilon,Math,Floating Point,Precision,Epsilon,因为我们知道0.1+0.2!=0.3由于数字表示有限,我们需要检查hatabs(0.1+0.2-0.3) > /P> 请注意,至少需要将此值按实际测试数的比例进行缩放。此外,由于精度仅与数值大致成比例,因此您可能希望将边距增加一小部分,以防止出现虚假错误: double epsilon = std::numeric_limits<double>::epsilon(); // C++ literals and math functions are double by default

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

ε的基线值是
1.0
和下一个最高可表示值之间的差值。在C++中,这个值可作为<代码> STD::NealICIONEXP::EpSelon()/< > > /P> 请注意,至少需要将此值按实际测试数的比例进行缩放。此外,由于精度仅与数值大致成比例,因此您可能希望将边距增加一小部分,以防止出现虚假错误:

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);
double epsilon=std::numeric_limits::epsilon();
//C++文字和数学函数默认为双倍

bool is_near=abs(0.1+0.2-0.3)您可以使用以下算法估计机器ε。您需要将这个ε乘以整数值
1+(log(number)/log(2))
。为方程式中的所有数字确定此值后,可以使用来估计特定计算的ε值

epsilon=1.0
而(1.0+(ε/2.0)>1.0){
ε=ε/2.0
}
//使用a+b的误差分析计算误差
epsilon_方程=Math.sqrt(2*epsilon*epsilon)
编写('Epsilon:'+Epsilon_方程+'
')) document.write('浮点错误:'+Math.abs(0.2+0.4-0.6)+'
')) document.write('使用epsilon进行比较:')
document.write(Math.abs(0.2+0.4-0.6)我知道以下精确计算浮点谓词的方法:使用标准浮点类型计算值,并计算错误。通常,谓词可以表示为
p(x)==0
p(x)<0
,等等。如果
p(x)的绝对值
大于误差,则认为计算是精确的。否则,将使用基于区间或精确有理数的算法

可以从使用的表达式中估计错误。我听说过这种自动生成器,但找不到任何参考

据我所知,精确计算主要用于几何,谷歌搜索“精确几何计算”在这方面有很多帮助


这在某种程度上解释了错误估计。

对我来说,
0.1+0.2=0.3
。你想把事情缩小到至少不包括十进制算法吗?你关心语言、芯片、操作系统,什么?似乎有点宽泛。这似乎太宽泛了。如果你使用浮点十进制,同样的答案也适用,即使是那个规范一个好的问题可以支持相当多的广度。好的,你有一点:根据上下文(和标签),这个问题实际上是关于浮点的。到目前为止的答案,虽然和预期的一样好,但似乎是在细节上下赌注,OP似乎需要细节。我开始同意@BillWoodger最初的评论,即这个问题太宽泛了。即使不考虑十进制算术,这也是一个活跃的研究课题。这是什么0.3*点(2*ε)=0.6(ε)?
0.3
是特征值。
2
是增加边距的小因素。在实际函数中,特征值将是输入的某种标准值……我将编辑我的答案,以包含一个更完整的示例。@comingstorm感谢您的回答!另外一句话:似乎应该检查一下如果参数是
0.0
,则为ed。否则
epsilon==0.0
,因此
近似等于(0.0,0.0)
将返回
false
。后续问题:在这种情况下如何检查等于
0.0
?使用std::numeric\u limits::min()?我认为将比较改为
不,这会得到绝对ε,不能用于比较,例如
abs(1.0+2.0-3.0)>epsilon
会给出
false
,不幸的是:(
abs(1.0+2.0-3.0)
中的错误是
sqrt(3*epsilon^2)
,所以对于这个方程,你应该使用这个值。这在我链接的PDF第3页中有解释。下面是我做的测试` Console.WriteLine(Math.Abs(1.0+2.0-3.0),这是C#,它打印出
False`在
1.0+2.0-3.0
中的错误为零。我会检查你的C#版本,但是,不精确通常只出现在小数部分,当转换时,会给出无限的二进制分数。1.0、2.0和3.0可以完美地表示为二进制数,因此我相信@tmyklebu是正确的。
bool is_approximately_equal(double a, double b) {
  double scale = max(abs(a), abs(b));
  return abs(a - b) <= scale * (2*epsilon);
}