【问题标题】:c++14 - Are DBL_Max and DBL_Min subject to round off errors?c++14 - DBL_Max 和 DBL_Min 是否会出现舍入错误?
【发布时间】:2018-06-23 00:03:39
【问题描述】:

浮点值可能存在舍入错误。例如,

double x = 1.0;
// x might be something like 1.00000000000000001

像 DBL_Max 和 DBL_Min 这样的常量是否总是保证具有它们预期的相同值(对于它们正在使用的任何系统)?他们是否可能受到四舍五入错误的影响?例如,在下面的代码中:

double x = DBL_Max;
assert (x == DBL_Max); // is this assertion guaranteed to always be true?

【问题讨论】:

    标签: floating-point double c++14 precision floating-accuracy


    【解决方案1】:

    C 和 C++ 标准对此没有明确规定。 C 标准允许在将源代码中的浮点常量(文字)转换为内部格式(如 C 2011 [N1570] 6.4.4.2 5 中)期间出现错误,并且对于 DBL_MAX 和 @ 的常量表达式没有明确禁止这种情况987654322@ 扩展至。但是,任何正常的 C 或 C++ 实现都不会有不准确的 DBL_MAXDBL_MIN 值。

    C++ 标准似乎确实表明,如果浮点文字是可表示的,则它们必须产生准确的值。 (C++ 2017 [draft n4659] 5.13.4 1 和 2010 版本中的类似文本:“如果缩放值在其类型的可表示值范围内,则结果是缩放值如果可表示,否则更大或更小可表示最接近缩放值的值,以实现定义的方式选择。”)但是,DBL_MAXDBL_MIN 被指定为常量表达式,而不是文字。我在 C++ 标准的规范部分中没有找到关于浮点表达式准确性的声明,但 5.19 4 中的注释说:“虽然在某些情况下必须在程序翻译期间评估常量表达式,但可能会在程序执行。由于本国际标准对浮点运算的准确性没有任何限制,因此未指定在翻译期间对浮点表达式的求值是否与对相同表达式的求值产生相同的结果(或对相同值的相同操作) ) 在程序执行期间。”

    因此,从技术上讲,该标准并不要求 x == DBL_MAXdouble x = DBL_MAX; 之后为真,但在实践中,它应该始终为真。

    如上所述,在 C++ 中,double x = 1.0; 中的 1.0 必须精确转换,因此 x 将被初始化为没有舍入错误的 1。 C 标准没有指定这一点,但没有一个健全的 C 实现会在double x = 1.0; 中出现舍入错误。舍入误差源于计算中的困难或不可能性,而不是随机伪影。

    【讨论】:

    • 在你最后一点的基础上,这是否意味着如果 x = 1.0, assert(x==1.0) 总是正确的?我想我在 SO 上看到了其他一些问题,如果将变量设置为文字,则会出现舍入错误。
    • @user18119:我在检查 C++ 5.13.4 1 之前输入了最后一段,这似乎表明可以准确表示的文字被准确翻译。所以1.0 应该总是精确地产生 1。(1 总是可以用浮点的定义来表示,它是某个基数中的一些数字乘以基数的某个幂,所以 1 总是可以表示为基数的 1 倍到零的幂。除非您想考虑指数零超出范围的奇怪浮点格式。)
    • @user18119:此外,C 标准允许在可以精确表示的情况下翻译带有舍入误差的文字的原因是编写好的软件来执行翻译具有多位数字的文字所需的算术和大的指数是困难的。它总是可以用小学教授的方法来完成,但有时可能需要编写软件来进行数百位数的算术运算,并且希望在小型机器上允许 C 语言。论文已经发表了很好的算法,所以现在做这项工作更容易......
    • ……但这种困难只适用于具有多位数字和大指数的数字。翻译1.0 和其他简单数字总是很容易,任何 C 实现都应该正确完成,即使标准在技术上允许不准确。
    • 好的,有道理。奇怪的是,C 标准在这方面没有更新为像 C++ 一样,但我认为这是由于向后兼容性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-15
    • 1970-01-01
    • 1970-01-01
    • 2011-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多