[英]Issue with floating point representation
int x=25,i;
float *p=(float *)&x;
printf("%f\n",*p);
我知道浮點數和int的位表示形式是不同的,但是無論我存儲什么值,答案始終是0.000000。 取決於浮點表示形式,它不應該是其他值嗎?
您的代碼具有未定義的行為-但只要int
和float
類型的大小和對齊方式兼容,它就很可能會按預期運行。
通過使用“%f”格式打印*p
,您將丟失很多信息。
嘗試這個:
#include <stdio.h>
int main(void) {
int x = 25;
float *p = (float*)&x;
printf("%g\n", *p);
return 0;
}
在我的系統上(可能在您的系統上),它會打印:
3.50325e-44
int
值25
大多數高階位都為零。 這些位可能與float
類型的指數字段位於同一位置-導致數量很少。
查找IEEE浮點表示以獲取更多信息。 字節順序將是一個問題。 (除非你有一個很好的理由不做這種事情在實際的代碼)。
正如rici在評論中所建議的那樣,了解浮點表示的更好方法是從浮點值開始,將其轉換為相同大小的無符號整數,然后以十六進制顯示整數值。 例如:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void show(float f) {
unsigned int rep;
memcpy(&rep, &f, sizeof rep);
printf("%g --> 0x%08x\n", f, rep);
}
int main(void) {
if (sizeof (float) != sizeof (unsigned int)) {
fprintf(stderr, "Size mismatch\n");
exit(EXIT_FAILURE);
}
show(0.0);
show(1.0);
show(1.0/3.0);
show(-12.34e5);
return 0;
}
為了便於討論,我們將假定int
和float
均為32位寬。 我們還將假設IEEE-754浮動。
浮點值表示為sign * β exp * signficand
。 對於32位二進制浮點數, β
為2
,指數exp
范圍是-126
至127
, 有效位數是歸一化的二進制分數,因此在基數點之前只有一個前導非零位。 例如, 25
的二進制整數表示為
11001 2
而25.0
的二進制浮點表示將是:
1.10012 * 24 // normalized
用於32位浮點的IEEE-754編碼為
s eeeeeeee fffffffffffffffffffffff
其中s
表示符號位, e
表示指數位, f
表示有效(分數)位。 指數使用“多余127”表示法編碼,這意味着指數值127
( 01111111 2
)代表0
,而1
( 00000001 2
)代表-126
而254
( 11111110 2
)代表127
。 有效位數的前導位未明確存儲,因此25.0
將被編碼為
0 10000011 10010000000000000000000 // exponent 131-127 = 4
但是,將32位整數值25
的位模式映射到32位浮點格式時會發生什么情況? 我們得出以下結論:
0 00000000 00000000000000000011001
事實證明,在IEEE-754浮點數中,保留了指數值00000000 2
來表示0.0
和非正規 (或非正規)數。 次普通數是接近0
,不能表示為1.??? * 2 exp
1.??? * 2 exp
,因為該指數必須小於我們可以在8位中編碼的指數。 這樣的數字被解釋為0.??? * 2 -126
0.??? * 2 -126
,根據需要有多個前導0
。
在這種情況下,它加起來為0.00000000000000000011001 2 * 2 -126
,從而得出3.50325 * 10 -44
。
您必須映射較大的整數值(超過2 24
),才能看到0以外的任何東西到一堆小數位。 而且,正如Keith所說的,無論如何這都是未定義的行為。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.