我已经被这个难住了好几天了。我根据一本名为 Write Great Code Volume 1 Understanding the Machine Chapter four 的书编写了这个程序。
该项目是用 C++ 进行浮点运算。我打算自己用C++实现其他操作;该书在项目中使用 HLA(高级程序集)进行乘法和除法等其他操作。
我想在从 FP 数字中提取指数和其他字段值后显示它们;用于调试。然而我有一个问题:当我在内存中查看这些值时,它们并不是我认为的那样。关键词:我的想法。我相信我了解 IEEE FP 格式;它相当简单,我理解到目前为止我在书中读到的所有内容。
最大的问题是为什么 Reexponent 变量看起来几乎不可预测;在此示例中,给定值为 5。这是为什么呢?我猜应该是两个。二是因为小数点是隐含的小数点右边的两位数。
我已将程序中产生的实际值注释到代码中,因此您不必运行程序即可了解发生了什么(至少在重要部分)。 此时尚未完成。整个项目还没有在我的电脑上创建。
这是代码(引用 self 从书中复制然后修改的文件):
#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;
}
帮助将不胜感激;我已经参与这个项目好几天了,非常沮丧!
最佳答案
in this example with the given values its 5. Why is that?
float 45.67在内部表示为
2^5 * 1.0110110101011100001010001111010111000010100011110110
实际上代表的是数字
45.6700000000000017053025658242404460906982421875
这是您在 float
中可以达到的最接近 45.67 的值。
如果您只对一个数的指数感兴趣,只需计算它的以 2 为底的对数并向下舍入即可。由于 45.67 介于 32 (2^5) 和 64 (2^6) 之间,因此指数为 5。
关于c++ - FP 数的指数字段不是我预期的,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25391313/