今天,我正在查看一些C++代码(由其他人编写)并找到了这一部分:
double someValue = ...
if (someValue < std::numeric_limits<double>::epsilon() &&
someValue > -std::numeric_limits<double>::epsilon()) {
someValue = 0.0;
}
Run Code Online (Sandbox Code Playgroud)
我试图弄清楚这是否有意义.
文档epsilon()说:
该函数返回1和大于1的最小值之间的差值,可以表示[乘双].
这是否也适用于0,即epsilon()最大值是否大于0?或者有没有之间的数字0,并0 + epsilon可以由代表double?
如果没有,那么比较不等于someValue == 0.0?
我认为abs并且fabs在使用时表现不同math.h.但是,当我只使用cmath和std::abs,我必须使用std::fabs或fabs?或者这不是定义?
我正在编写一些代码,其中包含以下内容:
double a = SomeCalculation1();
double b = SomeCalculation2();
if (a < b)
DoSomething2();
else if (a > b)
DoSomething3();
Run Code Online (Sandbox Code Playgroud)
然后在其他地方我可能需要做平等:
double a = SomeCalculation3();
double b = SomeCalculation4();
if (a == 0.0)
DoSomethingUseful(1 / a);
if (b == 0.0)
return 0; // or something else here
Run Code Online (Sandbox Code Playgroud)
简而言之,我有很多浮点数学正在进行,我需要对条件进行各种比较.我无法将其转换为整数数学,因为在这种情况下这样的事情毫无意义.
我以前读过浮点比较可能不可靠,因为你可以做这样的事情:
double a = 1.0 / 3.0;
double b = a + a + a;
if ((3 * a) != b)
Console.WriteLine("Oh no!");
Run Code Online (Sandbox Code Playgroud)
简而言之,我想知道:我如何可靠地比较浮点数(小于,大于,相等)?
我使用的数字范围大致是从10E-14到10E6,所以我确实需要使用小数字和大数字.
我已将此标记为语言无关,因为无论我使用何种语言,我都对如何实现此目标感兴趣.
int main()
{
float a = 0.7;
float b = 0.5;
if (a < 0.7)
{
if (b < 0.5) printf("2 are right");
else printf("1 is right");
}
else printf("0 are right");
}
Run Code Online (Sandbox Code Playgroud)
我本来期望这段代码的输出0 are right.但令我沮丧的是输出是什么1 is right原因?
http://msdn.microsoft.com/en-us/library/system.double.epsilon.aspx
如果创建一个自定义算法来确定是否可以将两个浮点数视为相等,则必须使用大于Epsilon常量的值来确定两个值相等的可接受的绝对差值.(通常,差异幅度比Epsilon大很多倍.)
那么这不是真正可以用于比较的ε吗?我真的不明白MSDN的措辞.
它可以在这里的示例中用作epsilon吗?- 浮动和双重比较最有效的方法是什么?
最后这看起来非常重要,所以我想确保我有一个可靠的实现平等,大于,小于,小于或等于,大于或等于.
C++ FAQ lite "[29.17]为什么我的浮点比较不起作用?" 建议这个相等测试:
#include <cmath> /* for std::abs(double) */
inline bool isEqual(double x, double y)
{
const double epsilon = /* some small number such as 1e-5 */;
return std::abs(x - y) <= epsilon * std::abs(x);
// see Knuth section 4.2.2 pages 217-218
}
Run Code Online (Sandbox Code Playgroud)
+0和-0?|x| < epsilon?更新
正如Daniel Daranas所指出的那样,最好调用函数isNearlyEqual(我关心的是这种情况).
有人指出了这个链接,我想更加突出地分享.
我有一个double价值f,并想要一个稍微大一点(或更小)的方法来获得一个新的值,该值尽可能接近原始值但仍严格大于(或小于)原始值.
它不必靠近最后一位 - 更重要的是,我所做的任何改变都能保证产生不同的值,而不是回到原始值.
double r = 11.631;
double theta = 21.4;
Run Code Online (Sandbox Code Playgroud)
在调试器中,这些显示为11.631000000000000和21.399999618530273.
我怎么能避免这个?
众所周知,在比较浮点值时必须小心.通常,==我们使用一些基于epsilon或ULP的相等测试来代替使用.
但是,我想知道,有什么案例,使用时==完全没问题吗?
看看这个简单的片段,哪些案例可以保证成功?
void fn(float a, float b) {
float l1 = a/b;
float l2 = a/b;
if (l1==l1) { } // case a)
if (l1==l2) { } // case b)
if (l1==a/b) { } // case c)
if (l1==5.0f/3.0f) { } // case d)
}
int main() {
fn(5.0f, 3.0f);
}
Run Code Online (Sandbox Code Playgroud)
注意:我已经检查了这个和这个,但它们不包括(全部)我的情况.
注2:似乎我必须添加一些加号信息,所以答案在实践中很有用:我想知道:
这是我在目前的标准草案中找到的唯一相关陈述:
浮点类型的值表示是实现定义的.[注意:本文档对浮点运算的准确性没有要求; 另见[support.limits]. - 结束说明]
那么,这是否意味着甚至"案例a)"是实现定义的?我的意思是,l1==l1绝对是一个浮点运算.那么,如果一个实现是"不准确的",那么可能l1==l1是假的?
我认为这个问题不是重复的浮点数==永远好吗?.这个问题没有解决我提出的任何案件.同一主题,不同的问题.我想特别针对案例a)-d)得到答案,因为我无法在重复的问题中找到答案.
c++ floating-point precision language-lawyer floating-point-comparison
我经常遇到需要检查获得的差异是否高于机器精度的情况。似乎为此目的,R 有一个方便的变量:.Machine$double.eps. 但是,当我转向 R 源代码以获取有关使用此值的指南时,我看到了多种不同的模式。
以下是stats库中的一些示例:
t.test.R
if(stderr < 10 *.Machine$double.eps * abs(mx))
Run Code Online (Sandbox Code Playgroud)
chisq.test.R
if(abs(sum(p)-1) > sqrt(.Machine$double.eps))
Run Code Online (Sandbox Code Playgroud)
积分
rel.tol < max(50*.Machine$double.eps, 0.5e-28)
Run Code Online (Sandbox Code Playgroud)
影响力
e[abs(e) < 100 * .Machine$double.eps * median(abs(e))] <- 0
Run Code Online (Sandbox Code Playgroud)
原理图
if (any(ev[neg] < - 9 * .Machine$double.eps * ev[1L]))
Run Code Online (Sandbox Code Playgroud)
等等。
10 *,100 *,50 *和sqrt()修饰?.Machine$double.eps用于调整因精度问题而导致的差异的指南?