像這樣的簡單代碼,根據下面的參考網站printf("hex representation for %f is [%a]\n", 3.14, 3.14);,我希望結果是0x4048f5c3(完整的二進制版本是:0100 0000 0100 1000 1111 0101 1100 0011,0x4.8f5c3p-1),但是編譯后的可執行檔案顯示[0xc.8f5c3p-2](二進制:)1100.1000 1111 0101 1100 0011,為什么 C 編譯器將指數顯示為 -2 而不是 -1 ?
編譯器設定是:
"command": "c:/msys64/mingw64/bin/gcc.exe",
"args": [
"-g",
"${file}",
"-o",
"${fileDirname}\\${fileBasenameNoExtension}.exe",
"-Wall",
"-Werror",
"-std=c11"
參考:https : //users.cs.fiu.edu/~downeyt/cop2400/float.htm https://gregstoll.com/~gregstoll/floattohex/
uj5u.com熱心網友回復:
您使用的網站正在顯示浮點數的二進制表示。例如,3.14是40 48 F5 C3big-endian,還是C3 F5 48 40little-endian。
C 中的十六進制表示是基數為 16 的實際浮點數,而不是二進制表示。0xc.8f5c3p-2是指c.8f5c3 * 2^(-2)。如果我們使用通常的轉換演算法將其轉換為十進制,我們會得到3.14:
12(C) * 16^0 8 * 16^(-1) 15(F) * 16^(-2) 5 * 16^(-3) 12(C) * 16^(-4) 3 * 16^(-5) = 12 0.5 0.05859 ... = 12.56 (有近似值)
現在乘以2^(-2)或除以4,我們得到3.14。
此處顯示了兩種表示之間的區別(請注意,該程式在技術上會導致 C 中的未定義行為,因為uint32_t*to float*cast 后跟取消參考,但在這種情況下,行為是使用二進制表示來創建浮點數,正如人們所期望的那樣):
#include <stdio.h>
#include <inttypes.h>
// Assuming IEE-754 representation of 32-bit floats
int main(void)
{
float x = 0xC.8F5C3p-2;
uint32_t y = 0x4048F5C3;
printf("Base-16 representation of %f is: %A\n", x, x);
printf("Binary representation of %f is: 0X%"PRIX32"\n", *(float*)&y, y);
}
這是我在電腦上得到的輸出:
Base-16 representation of 3.140000 is: 0XC.8F5C3P-2
Binary representation of 3.140000 is: 0X4048F5C3
uj5u.com熱心網友回復:
為什么 C 編譯器將指數顯示為 -2 而不是 -1?
這里的問題是浮點表示——無論是使用二進制、十進制還是十六進制——往往不是唯一的。查看以 10 為基數的數字,其科學記數法表示可能是
3.14 × 10 0
或者
0.314 × 10 1
或者甚至
31.4 × 10 -1
或者
0.0314 × 10 2
為了解決唯一性問題,我們通常定義一個“規范化形式”——但是可以有多種方法來進行定義!例如,我們可以說小數點左邊應該總是有一個數字 (3.14 × 10 0 ) - 或者我們可以說小數點左邊應該有 0 但立即有一個非零數字右側 (0.314 × 10 1 )。還有其他規范化規則的選擇。
然后,當涉及到printf %a它變得更加混亂,因為尾數數字是十六進制,但指數的冪2。因此,即使我們說我們想要小數點左側的“一個數字”,我們也有四種不同的數字可以是什么選擇,因為我們可以有效地將小數點放在一個十六進制數字的任何位之間!
我們可以用你 3.14 的例子來說明這一點。在二進制中,四舍五入到 24 個有效位(這是 IEEE 單精度,又名float),它是
0b1.10010001111010111000011 × 2 1
如果我們將其直接轉換為十六進制,我們會得到
0x1.91eb86 × 2 1
但是我們可以將有效數向左移動 1、2 或 3 位,并且小數點左側仍然只有一個十六進制數字:
0x3.23d70c × 2 0
0x6.47ae18 × 2 -1
0xc.8f5c30 × 2 -2
而且,事實上,在我的電腦上,%a列印3.14f為0x1.91eb86p 1. 但是你說你的列印出來了0xc.8f5c3p-2(@DarkAtom 也是這樣)。但正如我們剛剛看到的,這兩種表示是等價的。
正如其他答案和評論所解釋的那樣,您認為可能會看到的十六進制數0x4048f5c3與值沒有直接關系;它是 IEEE-754 單精度原始編碼的十六進制表示。隱藏在該編碼中的是 0 的符號位、 的有偏指數0x80和 的有效數,這取決于您如何看待它,0x91eb86或0x48f5c3。但是現在我們可以很容易地看到它們是如何組合在一起的,因為有效數與我們看到的十六進制模式相匹配,并且有偏差的指數值計算0x80為 128 - 127 = 1 的實際指數。(我說編碼的有效數是“取決于你如何看待它,0x91eb86或者0x48f5c3",但你可以相信我的話,這一切都對應于0x1.91eb86 × 21,其中前導 1 是隱式的。)
不過,我無法解釋0x4.8f5c3p-1你提到的那些來自哪里。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/368931.html
上一篇:BST中的后序
