c++14 - DBL_Max 和 DBL_Min 是否存在舍入误差?

c++14 - Are DBL_Max and DBL_Min subject to round off errors?

提问人:user18119 提问时间:6/23/2018 最后编辑:Dave2euser18119 更新时间:6/23/2018 访问量:206

问:

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

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?
C++14 浮点精度

评论


答:

0赞 Eric Postpischil 6/23/2018 #1

C 和 C++ 标准对此没有明确规定。C 标准允许在从源代码中的浮点常量(文字)转换为内部格式(如 C 2011 [N1570] 6.4.4.2 5)期间出现错误,并且没有明确禁止常量表达式 that 和 expand to 的错误。但是,任何理智的 C 或 C++ 实现都不会具有不准确的 或 值。DBL_MAXDBL_MINDBL_MAXDBL_MIN

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

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

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

评论

0赞 user18119 6/23/2018
基于你的最后一点,这是否意味着如果 x = 1.0,assert(x==1.0) 总是真的?我想我在 SO 上看到了其他一些问题,如果变量设置为文字,则会出现舍入误差。
1赞 Eric Postpischil 6/23/2018
@user18119:在检查 5.13.4 1 之前,我输入了最后一段C++,这似乎是说可以精确表示的文字被精确翻译。所以应该始终正好产生 1。(1 总是可以用浮点的定义来表示,浮点是某个基数中的一些数字乘以基数的某个幂,因此 1 总是可以表示为 1 乘以基数的 0 次方。除非你想考虑一种奇怪的浮点格式,其中指数零越界。1.0
0赞 Eric Postpischil 6/23/2018
@user18119:此外,C 标准允许以四舍五入误差翻译文字的原因是,即使它们可以精确表示,编写好的软件来执行翻译具有许多数字和指数的文字所需的算术是很困难的。它总是可以用小学教授的方法完成,但有时可能需要编写软件来做数百位数字的算术运算,并且希望在小型机器上允许使用C语言。此后,论文已经用良好的算法发表,所以现在更容易完成这项工作。
0赞 Eric Postpischil 6/23/2018
...但这种困难只适用于具有许多数字和大指数的数字。转换和其他简单数字总是很容易的,即使标准在技术上允许不准确,也应该由任何 C 实现正确完成。1.0
0赞 user18119 6/24/2018
Ok, makes sense. It's odd the C standard hasn't been updated to be like C++ on this, but I assume it's due to back compatibility.