2

如果我们运行这段代码:

 #include <iostream>
 int main ()
 { 
     using namespace std;
     float a = 2.34E+22f;
     float b = a+1.0f;  
     cout<<"a="<<a<<endl;
     cout<<"b-a"<<b-a<<endl;
     return 0;
 }

那么结果将为 0,因为浮点数只有 6 位有效数字。但浮点数 1.0 试图添加到数字的 23 位。那么,程序如何实现数字1没有位置,算法是什么?

4

3 回答 3

1

一步步:

IEEE-754 32 位二进制浮点格式:

    符号 1 位
    有效位 23 位
    指数 8 位

我)float a = 23400000000.f;

转换23400000000.ffloat

23,400,000,000 = 101 0111 0010 1011 1111 1010 1010 0000 0000 2 
               = 1.0101110010101111111010101000000000 2 • 2 34

但是有效位只能存储该点之后的 23 位。所以我们必须四舍五入:

  1.01011100101011111110101 01000000000 2 • 2 34 
≈ 1.01011100101011111110101 2 • 2 34

所以,之后:

float a = 23400000000.f;

a等于 23,399,991,808。

二)float b = a + 1;

a = 10101110010101111111010100000000000 2。
b = 10101110010101111111010100000000001 2 
  = 1.0101110010101111111010100000000001 2 • 2 34

但是,同样,有效位在该点之后只能存储 23 个二进制数字。所以我们必须四舍五入:

  1.01011100101011111110101 00000000001 2 • 2 34 
≈ 1.01011100101011111110101 2 • 2 34

所以,之后:

float b = a + 1;

b等于 23,399,991,808。

三)float c = b - a;

10101110010101111111010100000000000 2 - 10101110010101111111010100000000000 2 = 0

该值可以存储在float不四舍五入的情况下。

所以,之后:

float c = b - a;

с等于 0。

于 2013-08-16T09:03:36.757 回答
1

基本原则是两个数字对齐,使小数点在同一位置。我使用 10 位数字使其更易于阅读:

 a = 1.234E+10f;
 b = a+1.0f;

计算a+1.0f时,小数点需要对齐:

 1.234E+10f becomes 1234000000.0
 1.0f       becomes          1.0
            + 
            =       1234000001.0

但由于它是浮点数,右侧的 1 超出了有效范围,因此存储的数字将是1.234000E+10- 超出该数字的任何数字都将丢失,因为没有足够的数字。

[请注意,如果您在优化编译器上执行此操作,它可能仍将 1.0 显示为差异,因为浮点单元使用 64 位或 80 位内部表示,因此如果在没有将中间结果存储在变量(一个体面的编译器当然可以在这里实现)使用 2.34E+22f 它保证不适合 64 位浮点数,也可能不适合 80 位浮点数]。

于 2013-08-16T08:29:12.973 回答
0

将两个 FP 数相加时,首先将它们转换为相同的指数。十进制: 2.34000E+22 + 1.00000E0 = 2.34000E22 + 0.000000E+22. 在这一步中,1.0 丢失为四舍五入。

二进制浮点的工作原理几乎相同,除了 E+22 被 2^77 替换。

于 2013-08-16T14:05:26.267 回答