2016-04-30 114 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

相關問題