比较算子的数值精度

时间:2017-09-18 15:49:56

标签: c++ numerical-stability

简短问题:以最大精度定义的比较运算符的行为是什么? 意思是,如果我有两个数字(x和y)在精度上是相同的,那么当我做x<时,我总是期望得到相同的答案。 ÿ?

我意识到这似乎是一个愚蠢的问题,但让我详细说明。 我正在使用double,我有一系列数字,如:

0:  62536.5477752959
1:  62536.4840613718
2:  62536.4576412381
3:  62522.8487197062
4:  62536.5473896233
5:  62536.5467941254
6:  62527.3508907998
7:  62536.5477752959
8:  62517.5900098039
9:  62536.5477752959

请注意,条目0,7和9具有相同的值。

当我这样做时(

int low = 0, high = 0;
for(int i = 0; i < N; ++i) {
  if(x[i] < x[low])
    low = i;
  if(x[i] > x[high]) 
    high = i;
 }
 cout << "low: " << low << " high: " << high << endl;

我有时得到:low: 8 high: 0,有时:low: 8 high: 7 我本来期望总是最低的指数值。

有什么想法吗?

[编辑缺失的大括号。]

2 个答案:

答案 0 :(得分:4)

是的,假设您的浮点类型为IEEE754。任何两个doublexy表示x < yx == yx > y中只有一个成立,但一些边缘情况,如+ Inf,-Inf或NaN。

当您使用十进制表示法来表示浮点值时,会出现混淆;例如没有这样的double为62536.5477752959(或者您列表中的任何其他人)。

您提供的数字已被调试器/标准输出器截断,它们在您提供的实际算法中使用的数字。请确保相同的十进制数始终生成相同的double,此处不做任意选择:IEEE754要求选择最接近的double

如需进一步阅读,请参阅Is floating point math broken?

最后,将int i替换为int i = 0。目前,您的程序的行为是 undefined

答案 1 :(得分:2)

可以使用库来回避内置类型的行为/限制:

<强> Live On Coliru

pip install -U tensorflow tensorflow-gpu keras

打印

#include <boost/multiprecision/cpp_dec_float.hpp>
#include <algorithm>
#include <iostream>

int main() {
    using Float = boost::multiprecision::cpp_dec_float_100;
    std::vector<Float> values = {
        Float{ "62536.5477752959" }, Float{ "62536.4840613718" }, Float{ "62536.4576412381" }, Float{ "62522.8487197062" },
        Float{ "62536.5473896233" }, Float{ "62536.5467941254" }, Float{ "62527.3508907998" }, Float{ "62536.5477752959" },
        Float{ "62517.5900098039" }, Float{ "62536.5477752959" },
    };

    auto hilo = std::minmax_element(values.begin(),values.end());

    std::cout << "low: " << *hilo.first << " high: " << *hilo.second << std::endl;

}

打印索引:

low: 62517.6 high: 62536.5