FP号码的指数字段不是我预期的,为什么?

FP number's exponent field is not what I expected, why?

本文关键字:为什么 号码 指数 数字段 FP      更新时间:2023-10-16

我已经被这个问题难住好几天了。这个程序是我从一本叫《写好代码第一卷:理解机器》的书里选出来的。

这个项目是在c++中做浮点运算。我打算自己用c++实现其他的操作;本书在项目中使用HLA(高级汇编)进行乘法和除法等其他操作。

我想显示指数和其他字段值后,他们已经从FP数字提取;进行调试。然而,我有一个问题:当我在内存中查看这些值时,它们并不像我认为的那样。关键词:我的想法。我相信我理解IEEE FP格式;这本书相当简单,到目前为止我都能理解。

最大的问题是为什么指数变量似乎几乎不可预测;在这个例子中,给定的值是5。为什么呢?我猜应该是两个。2,因为小数点在隐含的小数点右边两位。

我已经将程序中产生的实际值注释到代码中,因此您不必运行程序来了解发生了什么(至少在重要部分)。在这一点上它是未完成的。整个项目还没有在我的计算机上创建。

下面是代码(引用自我从书中复制然后修改的文件):

#include<iostream>
typedef long unsigned real; //typedef our long unsigned ints in to the label "real" so we don't confuse it with other datatypes. 
using namespace std; //Just so I don't have to type out std::cout any more!
#define asreal(x) (*((float *) &x)) //Cast the address of X as a float pointer as a pointer. So we don't let the compiler truncate our FP values when being converted.
inline int extractExponent(real from) {
    return ((from >> 23) & 0xFF) - 127; //Shift right 23 bits; & with eight ones (0xFF == 1111_1111 ) and make bias with the value by subtracting all ones from it.
}

void fpadd ( real left, real right, real *dest) {
    //Left operand field containers
    long unsigned int Lexponent = 0;
    long unsigned     Lmantissa = 0;
    int               Lsign = 0;
    //RIGHT operand field containers
    long unsigned int Rexponent = 0;
    long unsigned     Rmantissa = 0;
    int               Rsign = 0;
    //Resulting operand field containers
    long int                Dexponent = 0;
    long unsigned   Dmantissa = 0;
    int             Dsign = 0;
    std::cout << "Size of datatype: long unsigned int is: " << sizeof(long unsigned int); //For debugging
    //Properly initialize the above variable's:
    //Left
    Lexponent = extractExponent(left); //Zero. This value is NOT a flat zero when displayed because we subtract 127 from the exponent after extracting it! //Value is: 0xffffff81
    Lmantissa = extractMantissa (left); //Zero. We don't do anything to this number except add a whole number one to it. //Value is: 0x00000000
    Lsign = extractSign(left); //Simple.
    //Right
    **Rexponent = extractExponent(right); //Value is: 0x00000005 <-- why???**
    Rmantissa = extractMantissa (right);
    Rsign = extractSign(right);

}
int main (int argc, char *argv[]) {
    real a, b, c;
    asreal(a) = -0.0;
    asreal(b) = 45.67;
    fpadd(a,b, &c);
    printf("Sum of A and B is: %f", c);
    std::cin >> a;
    return 0;
}

帮助将非常感激;我做这个项目有几天了,非常沮丧!

在本例中,

的值为5。为什么呢?

浮点数45.67在内部表示为

2^5 * 1.0110110101011100001010001111010111000010100011110110

实际表示的是数字

45.6700000000000017053025658242404460906982421875

这是float中最接近的45.67。

如果你感兴趣的是一个数字的指数,只需计算其以2为底的对数并向下舍入。因为45.67在32(2^5)和64(2^6)之间,所以指数是5。

计算机使用二进制表示所有的数字。因此,指数是以2为基数,而不是以10为基数。