【问题标题】:How to get the lowest representable floating point value in C++如何在 C++ 中获得最低可表示的浮点值
【发布时间】:2014-07-10 18:38:03
【问题描述】:

我有一个程序,我需要将一个变量设置为 C++ 中可表示的最低(非无限)双精度浮点数。如何将变量设置为最低的双精度浮点值?

我尝试使用 std::numeric_limits。我没有使用 C++11,所以我无法尝试使用最低()函数。我尝试使用 max(),但是当我尝试它时,它返回无穷大。我还尝试从 max() 中减去一个值,希望得到一个可表示的数字。

double max_value = std::numeric_limits<double>::max();
cout << "Test 1: " << max_value << endl;    
max_value = max_value - 1;
cout << "Test 2: " << max_value << endl;
double low_value = - std::numeric_limits<double>::max();
cout << "Test 3: " << low_value << endl;
cout << "Test 4: " << low_value + 1 << endl;

输出:

Test 1: inf
Test 2: inf
Test 3: -inf
Test 4: -inf

如何将上例中的 low_value 设置为可表示的最低双精度值?

【问题讨论】:

  • (C++11) 标准的 18.3.2.4 说 max() 是有限的。所以我猜 double 或 ostream 的实现是错误的。或者您可以尝试摆弄编译器选项,例如“精确浮点计算”等价物。
  • @PeterSchneider OP:“......我没有使用 C++11......”......
  • 只是出于好奇,cout &lt;&lt; std::numeric_limits&lt;double&gt;::max() 会打印什么? gcc wiki 有一些关于 80 位精度硬件与双打内存布局引起的问题的信息,但我不确定它是否真的适用于这里:gcc.gnu.org/wiki/FloatingPointMath
  • @Theolodis 这是我这里的那个;我无法想象max()s 的定义在标准之间发生了变化。毕竟不是max_plus_epsilon() ;-)
  • 'cout ::max()' 也打印无穷大。我的 iostream 一定有问题。

标签: c++ standard-library


【解决方案1】:

一旦你有了 -inf(你知道了),你就可以通过 (-inf,0) 上的 nextafter 函数获得最低的有限值。

编辑:根据上下文,这可能比-DBL_MAX 更好,以防DBL_MAX 以十进制表示(因此以不精确的方式)。然而,C 标准要求在默认舍入模式下评估浮点常量(即到最接近的)。在 GCC 的特殊情况下,DBL_MAX 是一个 long double 值转换为 double;但是 long double 值似乎有足够的数字,因此,一旦从十进制转换为 long double,该值就可以精确地表示为 double,因此强制转换是精确的,并且活动舍入模式不会影响它。如您所见,这相当棘手,可能需要在各种平台上检查它在任何情况下是否正确。以类似的方式,我严重怀疑 GCC 在 PowerPC 上定义 DBL_EPSILON 的正确性(其中 long double 类型被实现为 double-double arithmetic),因为有许多长双精度值非常接近两个。

【讨论】:

    【解决方案2】:

    标准库&lt;cfloat&gt;/&lt;float.h&gt; 提供了定义浮点实现参数的宏。

    这个问题有点模棱两可——不清楚您是指最小幅度可表示的非零值(即DBL_MIN)还是最低可表示的值值(由-DBL_MAX 提供)。无论哪种方式 - 根据需要进行选择。

    【讨论】:

    • 一般来说(例如在 IEEE 754 系统上),DBL_MIN 不是具有最小量级的数字,而是最小的正 正常 数。幅度最小的正数是 DBL_TRUE_MIN(好吧,在 C11 中,我不确定 C++),当你有 subnormals 时,这与 DBL_MIN 不同。
    • @vinc17 :似乎无论如何 -DBL_MAX 是无论如何都需要的。
    • 是的,但是DBL_MAX 可能存在实现问题:在某些情况下,它可能会产生不正确的值。
    • @vinc17 :正如您在回答中所说,取决于可能无关紧要的目的-在许多情况下,浮点并不容易以非常微妙的方式正确-对您的答案进行投票。
    • 我再次编辑了我的答案,因为 GCC 的定义实际上似乎是正确的,尽管它相当脆弱(例如,我不确定任何编译标志是否正确,并且它将来可能很容易损坏)。
    【解决方案3】:

    原来我用来打印值的 iostream 中有一个错误。我改用 cstdio 而不是 iostream。然后按预期打印这些值。

    double low_value = - std::numeric_limits<double>::max();
    cout <<"cout: " << low_value << endl;
    printf("printf: %f\n",low_value);
    

    输出:

    cout: inf
    printf: 179769...
    

    【讨论】:

    • 哦。将双精度打印为 int 并没有多大意义(双精度的 inf 位模式是什么?179 ...?)
    • 使用%f 打印双份
    • 对不起,那是我的错字。我在我的代码中使用了 %f,但出于习惯在这里写了 %d 而没有注意到。
    猜你喜欢
    • 2020-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-26
    • 1970-01-01
    • 1970-01-01
    • 2019-07-03
    相关资源
    最近更新 更多