2016-04-30 82 views
0

我想转换存储为int的十六进制值并将它们转换为使用IEEE 32位规则的浮点数。我特别努力为尾数和指数获得正确的值。十六进制以十六进制格式存储在文件中。我想要有四位有意义的人物。以下是我的代码。如何将十六进制转换为IEEE 754 32位浮点C++

float floatizeMe(unsigned int myNumba) { 
    //// myNumba comes in as 32 bits or 8 byte 

    unsigned int sign = (myNumba & 0x007fffff) >>31; 
    unsigned int exponent = ((myNumba & 0x7f800000) >> 23)- 0x7F; 
    unsigned int mantissa = (myNumba & 0x007fffff) ; 
    float value = 0; 
    float mantissa2; 

    cout << endl<< "mantissa is : " << dec << mantissa << endl; 

    unsigned int m1 = mantissa & 0x00400000 >> 23; 
    unsigned int m2 = mantissa & 0x00200000 >> 22; 
    unsigned int m3 = mantissa & 0x00080000 >> 21; 
    unsigned int m4 = mantissa & 0x00040000 >> 20; 

    mantissa2 = m1 * (2^-1) + m2*(2^-2) + m3*(2^-3) + m4*(2^-4); 

    cout << "\nsign is: " << dec << sign << endl; 
    cout << "exponent is : " << dec << exponent << endl; 
    cout << "mantissa 2 is : " << dec << mantissa2 << endl; 

    // if above this number it is negative 
    if (sign == 1) 
     sign = -1; 

    // if above this number it is positive 
    else { 
     sign = 1; 
    } 

    value = (-1^sign) * (1+mantissa2) * (2^exponent); 
    cout << dec << "Float value is: " << value << "\n\n\n"; 

    return value; 
} 




    int main() 
{ 
    ifstream myfile("input.txt"); 
    if (myfile.is_open()) 
    { 
     unsigned int a, b,b1; // Hex 
     float c, d, e; // Dec 
     int choice; 

     unsigned int ex1 = 0; 
     unsigned int ex2 = 1; 
     myfile >> std::hex; 
     myfile >> a >> b ; 
     floatizeMe(a); 
myfile.close(); 
return 0; 

}

+4

'2^-1'(等等)应该计算什么? – usr2564301

+1

您的'sign'位总是0. – usr2564301

+2

如果您尝试将**转换为** IEEE 754 32位,那么输入的表示是什么? – user2079303

回答

2

我怀疑你在

mantissa2 = m1 * (2^-1) + m2*(2^-2) + m3*(2^-3) + m4*(2^-4); 

意味着为^意味着 “给力”。 C或C++中没有这样的操作符。 ^运算符是按位异或的运算符。

+0

谢谢你是一个问题。另一个是我抓住了23位和22位。在这和你的帮助之间,我得到了正确的尾数。 –

+1

@SamArnold如果你接受我的回答,我不会不高兴,然后...... :) – Jfevold

0

考虑到您的CPU遵循IEEE标准,您还可以使用union。这样

union 
    { 
    int num; 
    float fnum; 
    } my_union; 

东西然后整数值存入my_union.num并通过获取my_union.fnum读取它们为浮动。

0

除了更简单之外,这也避免了任何舍入/精度错误。

float value = reinterpret_cast<float&>(myNumba) 

如果你还是想单独检查部位,使用库函数std::frexp之后。如果你不喜欢类型双关语,至少使用std::ldexp来应用指数而不是你的显式数学,这是易于舍入/精度错误和溢出。

这两者的替代方法是使用联合类型,如this answer中所述。

0

在你的代码中有很多基本错误。

最明显的是反复使用^为“权力”。 ^是XOR运算符,对于“功率”,您必须使用math.h中的函数pow(base, exponent)

接下来,“我想有四位有效数字”(可能是尾数),但是您只提取四位。四位只能编码0..15,大约是一位半。要获得四位有效数字,您至少需要log(10,000)/ log(2)≈13.288或至少14位(但最好是17位,因此您可以获得一个完整的额外数字以获得更好的舍入)。

您提取了sign的错误位,然后以错误的方式使用它。是的,如果它是0然后sign = 1如果1然后sign = -1,但你使用它在最终计算为

value = (-1^sign) * ... 

(再次用^,虽然连pow没有任何意义在这里)。你应该马上使用sign * ..

exponent被宣布为unsigned int,但失败的负值。它需要signedpow(2, exponent)(从您的(2^exponent)更正)。

积极的一面,(1+mantissa2)确实是正确的。

将所有这些要点放在一起,而忽略了实际只要求4位有效数字这一事实,我会得到以下代码。请注意,我重新安排了初始位移和提取以方便 - 我将mantissa转换为左侧,而不是右侧,因此我可以在其计算中测试0

(啊,我错过了!)立即使用sign不起作用,因为它被宣布为unsigned int。因此,如果您认为您给它的值为-1,它实际上得到的值为4294967295(更精确地说,值为UINT_MAX,从limits.h)。

摆脱此问题的最简单方法不是乘以sign,而是仅对其进行测试,如果已设置,则取消value

float floatizeMe (unsigned int myNumba) 
{ 
    //// myNumba comes in as 32 bits or 8 byte 

    unsigned int sign = myNumba >>31; 
    signed int exponent = ((myNumba >> 23) & 0xff) - 0x7F; 
    unsigned int mantissa = myNumba << 9; 
    float value = 0; 
    float mantissa2; 

    cout << endl << "input is : " << hex << myNumba << endl; 
    cout << endl << "mantissa is : " << hex << mantissa << endl; 

    value = 0.5f; 
    mantissa2 = 0.0f; 
    while (mantissa) 
    { 
     if (mantissa & 0x80000000) 
      mantissa2 += value; 
     mantissa <<= 1; 
     value *= 0.5f; 
    } 

    cout << "\nsign is: " << sign << endl; 
    cout << "exponent is : " << hex << exponent << endl; 
    cout << "mantissa 2 is : " << mantissa2 << endl; 

    /* REMOVE: 
     if above this number it is negative 
    if (sign == 1) 
     sign = -1; 

    // if above this number it is positive 
    else { 
     sign = 1; 
    } */ 

    /* value = sign * (1.0f + mantissa2) * (pow (2, exponent)); */ 
    value = (1.0f + mantissa2) * (pow (2, exponent)); 
    if (sign) value = -value; 
    cout << dec << "Float value is: " << value << "\n\n\n"; 

    return value; 
} 

通过以上,你得到的值正确的结果,如0x3e4ccccd(0.2000000030)和0x40490FDB(3.1415927410)。

如果你的输入已经是IEEE-754格式(尽管是十六进制格式),那么所有的说明和完成,那么简单的演员就足够了。

+0

谢谢Rad Radus。这是第一个C++项目之一。所以我没有意识到诸如^的意思是按位进行的。很多你修复的代码。不幸的是,标志仍然有些问题。我将标志切换到32位,现在它有正确的答案,但对于负数来说是错误的。但除此之外,非常感谢你。 –

+0

@SamArnold:你是正确的,因为负数不能与我的代码一起工作,对不测试的道歉。 **然而**,你建议的“32位移位”的修正是*错误的* - 你最终会一直为零!看到我的'哎呀'除了上面的正确的修复。 – usr2564301

相关问题