【C语言进阶深度学习记录】三 浮点数(float) 在内存中的表示方法
- 相信大多數(shù)人知道整形數(shù)在內(nèi)存中的分布方式,而且也能很容易寫(xiě)出其二進(jìn)制的形式,但是對(duì)于浮點(diǎn)數(shù),估計(jì)知道的人并不是很多
- 今天學(xué)習(xí)在C語(yǔ)言中浮點(diǎn)數(shù)在內(nèi)存中的表示方法
文章目錄
- 1 浮點(diǎn)數(shù)在內(nèi)存中的存儲(chǔ)方式
- 1.1 浮點(diǎn)數(shù)的轉(zhuǎn)換步驟
- 1.2 浮點(diǎn)數(shù)的轉(zhuǎn)換實(shí)際例子分析
- 1.3 編程驗(yàn)證測(cè)試
- 2 int與float類(lèi)型的范圍的比較
- 2.1 float數(shù)不精確的編碼案例
- 3 總結(jié)
1 浮點(diǎn)數(shù)在內(nèi)存中的存儲(chǔ)方式
- 浮點(diǎn)數(shù)在內(nèi)存中的存儲(chǔ)方式為:符號(hào)位+指數(shù)+尾數(shù)。對(duì)于float與double類(lèi)型的存儲(chǔ)方式,如下圖所示:
- float與double類(lèi)型的數(shù)據(jù)在計(jì)算機(jī)內(nèi)部的表示法是相同的,但是由于所占存儲(chǔ)空間的不同,其分別能表示的數(shù)值范圍和精度不同。
上面的表示法,可能并不是很好理解,看到后面的例子就會(huì)恍然大悟。
1.1 浮點(diǎn)數(shù)的轉(zhuǎn)換步驟
具體如何將浮點(diǎn)數(shù)轉(zhuǎn)換成內(nèi)存中的二進(jìn)制(或者十六進(jìn)制的形式),下面就來(lái)看看轉(zhuǎn)換步驟。
- 注意,第三點(diǎn)需要明白,計(jì)算指數(shù)時(shí)需要加上偏移量(這里不講解為什么存在偏移量,后序文章會(huì)學(xué)習(xí)),對(duì)于float與double類(lèi)型,加上的偏移量是不一樣的。具體如下:
對(duì)于指數(shù)為6,偏移后的值為:
float:6+127 ---->> 133
double : 6+1023 ---->> 1029
對(duì)于上面的內(nèi)容,目前可能還沒(méi)有理清。但是下面的例子,可以將上面的所有內(nèi)容學(xué)習(xí)明白
1.2 浮點(diǎn)數(shù)的轉(zhuǎn)換實(shí)際例子分析
上面說(shuō)了一堆,這里來(lái)一個(gè)例子徹底明白上述的轉(zhuǎn)換規(guī)則。
- 實(shí)數(shù)8.25在內(nèi)存中的float表示為如下:
首先是確定8.25的二進(jìn)制表示形式:1000.01
然后用科學(xué)技術(shù)法表示二進(jìn)制浮點(diǎn)數(shù):1.00001 * (23).
計(jì)算符號(hào)位:3+127 = 130 ----> 10000010
符號(hào)位為0, 10000010 , 小數(shù)為(尾數(shù)):00001
由上面4條的計(jì)算以及前面的規(guī)則,得到8.25的float表示為:
- 0 10000010 00001000000000000000000 ----> 0x41040000
至此,已經(jīng)得出了8.25的浮點(diǎn)數(shù)表示形式。對(duì)于double的表示形式,可以自己進(jìn)行推導(dǎo)。
1.3 編程驗(yàn)證測(cè)試
對(duì)于1.2小節(jié)的內(nèi)容,可以編寫(xiě)下面的程序來(lái)進(jìn)行驗(yàn)證:
#include <stdio.h>int main() {float f = 8.25;unsigned int* p = (unsigned int*)&f;printf("0x%08X\n", *p);return 0; }運(yùn)行結(jié)果也是等于: 0x41040000 可以驗(yàn)證上述規(guī)則與推導(dǎo)的正確性。
2 int與float類(lèi)型的范圍的比較
我們知道int與float都是占用4字節(jié)內(nèi)存,但是他們所能夠表示的數(shù)的范圍并不是一樣的。如下圖:
- int 類(lèi)型的范圍:[-231 , 231]
- float類(lèi)型的范圍:[-3.4 * 1038 , 3.4 * 1038]
首先拋開(kāi)float為什么是這個(gè)范圍不說(shuō)(具體的原因本文不講)。為什么int和float同樣是占用4字節(jié)的內(nèi)存,但是float所表示的數(shù)的范圍明顯比int的范圍大很多?
其實(shí)只要占用的字節(jié)數(shù)相同,那么所能表示的數(shù)的個(gè)數(shù),就一定相等,比如一字節(jié)的內(nèi)存就最多能表示 256個(gè)數(shù)字。但是有符號(hào)和無(wú)符號(hào)表示的數(shù)范圍就不一樣。注意,是數(shù)范圍不一樣,但是他們都只能表示256個(gè)數(shù)字。只是這256個(gè)數(shù)字的范圍不在同一個(gè)區(qū)間。
那么float也是一樣,它也是只能表示與int類(lèi)型一樣多的數(shù)字,只是float表示的數(shù)的范圍是上面的那樣而已。它能表示的數(shù)的范圍很大,不要被這一點(diǎn)迷惑。
- 可能我們覺(jué)得[-3.4 * 1038 , 3.4 * 1038] 這個(gè)區(qū)間很大,它的個(gè)數(shù)比int表示的個(gè)數(shù)多很多。 注意,這個(gè)想法是錯(cuò)誤的!!!
- float所表示的數(shù)不是連續(xù)的數(shù),在[-3.4 * 1038 , 3.4 * 1038]這個(gè)區(qū)間,存在很多空洞,只有少部分是表示float的數(shù)。
- float只是一種近似的表示法,不能作為精確數(shù)使用。
當(dāng)然這一切,都是由于float的內(nèi)存表示法的不同造成的。有興趣的人可以研究一下,上述float的數(shù)的范圍區(qū)間是如何來(lái)的。
2.1 float數(shù)不精確的編碼案例
看下面的代碼:
#include <stdio.h>int main() {float f = 3.1415f;float fl = 123456789;printf("%0.10f\n", f);printf("%0.10f\n", fl);return 0; }編譯運(yùn)行結(jié)果為:
3.1414999962 123456792.0000000000這個(gè)結(jié)果貌似與我們所期盼的結(jié)果有很大的出入。但是 這就是正常的結(jié)果,因?yàn)閒loat表示的數(shù)是不精確的,像上面的數(shù)3.1415f ,float就無(wú)法表示這樣的數(shù),雖然它在區(qū)間[-3.4 * 1038 , 3.4 * 1038]中,但是float就是無(wú)法精確表示它,只能打印它最接近這個(gè)數(shù)的一個(gè)數(shù)。所以打印結(jié)果是另一個(gè)數(shù)。
- 這也驗(yàn)證了上面關(guān)于說(shuō)float無(wú)法精確表示一個(gè)數(shù)的說(shuō)法
3 總結(jié)
- 浮點(diǎn)數(shù)與整形數(shù)的內(nèi)存表示法不同
- 浮點(diǎn)數(shù)類(lèi)型可表示的范圍更大
- 浮點(diǎn)類(lèi)型是一種不精確的類(lèi)型
- 由于浮點(diǎn)數(shù)的內(nèi)存表示法比較復(fù)雜,所以浮點(diǎn)數(shù)的運(yùn)算速度很慢
- float所表示的數(shù)不是連續(xù)的數(shù)
總結(jié)
以上是生活随笔為你收集整理的【C语言进阶深度学习记录】三 浮点数(float) 在内存中的表示方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 安装oracle-java,并覆盖原先的
- 下一篇: 源码安装Bazel