我已经被困在这一天好几天了。我从一本名为Write Great Code Volume 1 Understanding the Machine Chapter 4的书中写了这个程序。
该项目是用C ++进行浮点运算。我计划用自己的C ++实现其他操作;本书在项目中使用HLA(高级程序集)进行乘法和除法等其他操作。
我想在从FP号中提取后显示指数和其他字段值;用于调试。然而我遇到了一个问题:当我在记忆中看到这些价值时,他们并不是我认为应该是的。关键词:我的想法。我相信我理解IEEE FP格式;它非常简单,我理解到目前为止我在书中所阅读的内容。
最大的问题是为什么Rexponent变量似乎几乎不可预测;在这个例子中,给定值为5.为什么?根据我的猜测它应该是两个。两个因为小数点是隐含的小数点的两位数。
我已经将程序中产生的实际值注释到代码中,因此您无需运行程序即可了解发生的事情(至少在重要部分中)。 目前尚未完成。尚未在我的计算机上创建整个项目。
这是代码(引自我从书中复制然后修改的文件):
#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;
}
非常感谢帮助;我有几天参加这个项目并非常沮丧!
答案 0 :(得分:3)
在此示例中,给定值为5.为什么会这样?
浮点数45.67在内部表示为
2^5 * 1.0110110101011100001010001111010111000010100011110110
实际上代表数字
45.6700000000000017053025658242404460906982421875
尽可能接近float
内的45.67。
如果您感兴趣的只是数字的指数,只需计算其基数2的对数并向下舍入。由于45.67介于32(2 ^ 5)和64(2 ^ 6)之间,因此指数为5.
答案 1 :(得分:2)
计算机对所有数字使用二进制表示。因此,指数是基数为2,而不是基数为10。 int(log2(45.67))= 5.