【问题标题】:IEEE 754 Addition of two 32-bit floating point numbers (-1 and 2^(-50) )IEEE 754 两个 32 位浮点数的加法(-1 和 2^(-50) )
【发布时间】:2021-12-14 16:35:41
【问题描述】:

考虑以下一段 C++ 代码:

#include <iostream>
#include <cmath>

using namespace std;

int main()
{
    cout.precision(1000000000);
    
    float a,b,c;
    
    a = 1;
    b = -1;
    c = pow(2, -50);
    
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "c = " << c << endl;
    
    float ab = a + b;
    float bc = b + c;
    float abc = ab + c;
    float bca = bc + a;
    
    cout << "a + b = " << ab << endl;
    cout << "b + c = " << bc << endl;
    cout << "(a + b) + c = " << abc << endl;
    cout << "(b + c) + a = " << bca << endl;

    return 0;
}

产生输出:

a = 1
b = -1
c = 8.8817841970012523233890533447265625e-16
a + b = 0
b + c = -1
(a + b) + c = 8.8817841970012523233890533447265625e-16
(b + c) + a = 0

为什么 b + c = -1?

我无法理解 IEEE 754 标准的这种影响。

据我了解,指数范围从 -126 到 127。(偏置指数为 8 位,偏置为 127。)

所以 2^(-50) 可以毫无问题地表示为 1 或 -1。如果我正确理解标准,它们都不是次规范(非规范化)数字。

但是为什么-1 + 2^(-50)的加法会导致-1,从而忽略较小的数字呢?

提前感谢您的帮助!

【问题讨论】:

  • 相比-12^(-50)基本算不了什么。 double 只能得到 15-16 位或精度,将 8.9e-16 添加到 -1 基本上是舍入误差。
  • 十进制数学提示:什么是 1.00 + 0.00100,四舍五入到 3 位有效数字?
  • @PeteBecker:IEEE-754 单精度二进制数根本没有十进制数字,将它们视为十进制数字是一种误导模型,会导致错误。 1.40129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125•10^−45 有 105 个有效数字,但准确表示为无特别是,将“噪声”视为格式精度的一部分,而不是由执行的计算产生的,这会干扰正确计算误差范围。
  • 初学者最好被告知每个操作,包括十进制数字和二进制浮点格式之间的转换,可能会在每个值时引入一些“噪音” 正好代表一个数字。这就是它在 IEEE-754 标准中的规定,也是正确设计、推理、分析和调试浮点代码所需的模型。你有一个浮点数并不是事实,这意味着一些数字是“噪音”;事实上,您使用的运算只能逼近实数算术,这会给您带来“噪音”。
  • 圆运算和浮点运算都是数字,这不是一个难理解的概念。

标签: c++ floating-point addition ieee-754


【解决方案1】:

IEEE 754 标准为尾数指定 1 个符号位、7 个指数位和 24 个位。执行加法时,每个数字的尾数都被归一化,因此 2^-50 相对于 1 右移 1 50 位。这会导致它落在用于结果的 24 位尾数之外。你应该尝试用 2^-25 重复你的实验来证明这一点。

【讨论】:

  • 谢谢!我不敢相信我花了这么多时间来弄清楚 - 最终 - 非常简单的事情。 -1 + 2^(-25) 也导致 -1。但是 -1 + 2^(-24) 的结果是 -0.999999940395355224609375,考虑到您的解释,这是有道理的。
  • IEEE-754 单精度二进制格式具有一位符号、近八位指数(不是七位)和 24 位有效数。这是用 1 位的符号编码,8 位的指数加上一些附加信息,以及 23 位的主要有效数编码。 (第 24 位有效位通过指数字段编码。)
  • “有效数”是浮点表示的小数部分的首选术语。 “尾数”是对数的小数部分的旧术语。尾数是对数的(加上尾数乘以表示的数字)。有效数字是线性的(添加有效数字会增加所代表的数字)。
【解决方案2】:

您正在使用float,它(至少)是单精度的。请改用double

并且-1+9e-16 在单精度的-1 的舍入范围内。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-16
    • 1970-01-01
    • 2013-07-24
    • 1970-01-01
    • 1970-01-01
    • 2017-07-21
    • 2012-01-06
    相关资源
    最近更新 更多