相关疑难解决方法(0)

使用epsilon将double比较为零

今天,我正在查看一些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

c++ double

209
推荐指数
4
解决办法
5万
查看次数

我什么时候使用fabs什么时候使用std :: abs就足够了?

我认为abs并且fabs在使用时表现不同math.h.但是,当我只使用cmathstd::abs,我必须使用std::fabsfabs?或者这不是定义?

c++ math.h cmath

96
推荐指数
3
解决办法
6万
查看次数

我该如何进行浮点比较?

我正在编写一些代码,其中包含以下内容:

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,所以我确实需要使用小数字和大数字.

我已将此标记为语言无关,因为无论我使用何种语言,我都对如何实现此目标感兴趣.

language-agnostic floating-point comparison

73
推荐指数
4
解决办法
6万
查看次数

浮点比较

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原因?

c c++ floating-point

63
推荐指数
2
解决办法
1万
查看次数

Double.Epsilon表示相等,大于,小于,小于或等于,大于或等于

http://msdn.microsoft.com/en-us/library/system.double.epsilon.aspx

如果创建一个自定义算法来确定是否可以将两个浮点数视为相等,则必须使用大于Epsilon常量的值来确定两个值相等的可接受的绝对差值.(通常,差异幅度比Epsilon大很多倍.)

那么这不是真正可以用于比较的ε吗?我真的不明白MSDN的措辞.

它可以在这里的示例中用作epsilon吗?- 浮动和双重比较最有效的方法是什么?

最后这看起来非常重要,所以我想确保我有一个可靠的实现平等,大于,小于,小于或等于,大于或等于.

c# epsilon

52
推荐指数
5
解决办法
5万
查看次数

将浮点数与零进行比较

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)
  1. 这是否正确,这意味着唯一等于零的数字是+0-0
  2. 当测试零或者测试时,是否应该使用此功能|x| < epsilon

更新

正如Daniel Daranas所指出的那样,最好调用函数isNearlyEqual(我关心的是这种情况).

有人指出了这个链接,我想更加突出地分享.

c++ floating-point

52
推荐指数
5
解决办法
8万
查看次数

如何以最小增量(或接近它)改变浮点数?

我有一个double价值f,并想要一个稍微大一点(或更小)的方法来获得一个新的值,该值尽可能接近原始值但仍严格大于(或小于)原始值.

它不必靠近最后一位 - 更重要的是,我所做的任何改变都能保证产生不同的值,而不是回到原始值.

c c++ floating-point

47
推荐指数
3
解决办法
7691
查看次数

为什么我看到一个双变量初始化为某个值,如21.4为21.399999618530273?

double r = 11.631;
double theta = 21.4;
Run Code Online (Sandbox Code Playgroud)

在调试器中,这些显示为11.63100000000000021.399999618530273.

我怎么能避免这个?

floating-point precision

46
推荐指数
5
解决办法
2万
查看次数

浮点平等

众所周知,在比较浮点值时必须小心.通常,==我们使用一些基于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:似乎我必须添加一些加号信息,所以答案在实践中很有用:我想知道:

  • C++标准说的是什么
  • 如果C++实现遵循IEEE-754会发生什么

这是我在目前的标准草案中找到的唯一相关陈述:

浮点类型的值表示是实现定义的.[注意:本文档对浮点运算的准确性没有要求; 另见[support.limits]. - 结束说明]

那么,这是否意味着甚至"案例a)"是实现定义的?我的意思是,l1==l1绝对是一个浮点运算.那么,如果一个实现是"不准确的",那么可能l1==l1是假的?


我认为这个问题不是重复的浮点数==永远好吗?.这个问题没有解决我提出的任何案件.同一主题,不同的问题.我想特别针对案例a)-d)得到答案,因为我无法在重复的问题中找到答案.

c++ floating-point precision language-lawyer floating-point-comparison

46
推荐指数
3
解决办法
3391
查看次数

检查差异是否小于机器精度的正确/标准方法是什么?

我经常遇到需要检查获得的差异是否高于机器精度的情况。似乎为此目的,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)

等等。

问题

  1. 一个如何理解这些不同背后的理由10 *100 *50 *sqrt()修饰?
  2. 是否有关于.Machine$double.eps用于调整因精度问题而导致的差异的指南?

floating-point precision r rounding

36
推荐指数
2
解决办法
1276
查看次数