c++ - C - 对双变量求和会根据其编写方式给出不同的输出
问题描述
我有这些变量:
double a = 5;
double b = 1E20;
double c = -b;
我总结他们是这样的:
double temp = a+b;
double result = temp+c;
结果等于0,正如预期的那样,因为'b'与'a'相比是一个很大的数字,因此结果与b的数字完全不同,并用'c'减去它,这与'相同' b' 但为负,给我们 0。但是,如果我这样尝试:
double result = (a+b)+c;
结果实际上是 8。这是为什么呢?
解决方案
假设您正在英特尔处理器上执行此程序。(当问这样的问题时,你应该总是说明你正在使用哪个编译器,包括版本和命令行开关,以及你在哪个系统上运行程序。)英特尔处理器有 80 位浮点格式,它有 64 位有效位。(有效数是浮点数的小数部分。)
看来您的编译器正在使用处理器的 80 位浮点格式进行中间计算,并且它可能使用 IEEE-754 基本 64 位二进制格式来处理double
. C 标准允许 C 实现以比标称类型更大的范围和精度来评估浮点表达式。这意味着,当编译器评估(或生成代码以评估)double
表达式时,允许使用 80 位类型。
当将浮点表达式分配给对象或显式强制转换为浮点类型时,C 标准要求 C 实现“丢弃”超出的精度。
以上让我们看到发生了什么。1e20
表示 10 20,它是介于 2 66和 2 67之间的数字。以二进制形式写入,其前导位位于值 2 66的位置。由于 80 位格式具有 64 位有效位,因此可以在格式中表示的最低有效位位于位置 2 3(从 3 到 66 的位为 64 位)。之后b = 1e20
,当您将 5 添加到 时b
,必须将结果四舍五入以适合从 2 66到 2 3(即 8)的位。这导致将数字四舍五入到下一个 8 的倍数。因此,由于四舍五入,b+5
结果与 相同b+8
。然后,当你添加c
,等于-b
,你得到 8。
在double temp = a+b;
中,赋值强制 C 实现“丢弃”多余的精度。因此,它必须将结果转换为double
具有 53 位有效位的格式。前导位为 2 66,最低有效位为 2 14。2 13到 2 3的位被丢弃,其余位被舍入(在这种情况下不会导致任何变化,因为丢弃的位恰好小于中点)。因此,尽管a+b
equals b+8
,正如我们在上面看到的,转换b+8
为的结果double
是 just b
。然后添加c
到这个产生0。
推荐阅读
- request - 我怎么称呼未来
在颤动中休息api? - poppler - pdf2HtmlEX - html 上的文本与源 pdf 不同
- tizen - 本机 Tizen 3.0 表盘严重错误。对待:2
- python - /post/106/ 处的 AttributeError
- caching - Apache NiFi 集群中的分布式地图缓存问题
- java - JavaFX LineChart delta 必须是正异常
- php - Ajax 从数据库中检查多个相同类型行的重复数据
- python - Google Sheets API 错误:invalid_user:机器人缺少项目编号
- python - 带有神经网络思维的简单逻辑回归
- reactjs - Webpack 4 编译器错误 ERROR in compilation.fileDependencies.push is not a function