日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

int, float, double之间不得不说的故事

發(fā)布時(shí)間:2023/12/18 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 int, float, double之间不得不说的故事 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

抱歉我用了一個(gè)這么“二”的題目,不過(guò)二點(diǎn)就二點(diǎn)吧,希望內(nèi)容還不算太二。
其實(shí)學(xué)習(xí)過(guò)編程的同學(xué),都對(duì)這三個(gè)東西再熟悉不過(guò)了。int,又稱(chēng)作整型,在.net中特指的是Int32,為32位長(zhǎng)度的有符號(hào)整型變量。float,單精度浮點(diǎn)數(shù),32位長(zhǎng)度,1位符號(hào)位,8位指數(shù)位與23位數(shù)據(jù)位,在.net中又稱(chēng)為Single。double,64位長(zhǎng)度的雙精度浮點(diǎn)數(shù),1位符號(hào)位,11位指數(shù)位,52位數(shù)據(jù)位。它們互相的關(guān)系就是:int可以穩(wěn)式轉(zhuǎn)換成float和double,float只能強(qiáng)制轉(zhuǎn)換成int,但是可以隱式轉(zhuǎn)換成double,double只能強(qiáng)制轉(zhuǎn)換成float和int。
在說(shuō)明問(wèn)題之前,還很有必要溫習(xí)一下計(jì)算機(jī)組成原理時(shí)學(xué)習(xí)到的一些知識(shí),就是二進(jìn)制補(bǔ)碼表示以及浮點(diǎn)數(shù)表示。我想把一個(gè)十進(jìn)制轉(zhuǎn)化為二進(jìn)制的方法已經(jīng)不用多費(fèi)唇舌,只不過(guò)為了計(jì)算方便以及消除正零與負(fù)零的問(wèn)題,現(xiàn)代計(jì)算機(jī)技術(shù),內(nèi)存里存的都是二進(jìn)制的補(bǔ)碼形式,當(dāng)然這個(gè)也沒(méi)什么特別的,只不過(guò)有某些離散和點(diǎn),需要特殊定義而已,比如-(2^31),這個(gè)數(shù)在int的補(bǔ)碼里表示成1000…(31個(gè)零),這個(gè)生套補(bǔ)碼計(jì)算公式并不能得到結(jié)果(其實(shí)不考慮進(jìn)位的話還真是這個(gè)結(jié)果,但是總讓人感覺(jué)很怪)。再者,浮點(diǎn)數(shù),其實(shí)就是把任何二進(jìn)制數(shù)化成以0.1....開(kāi)頭的科學(xué)計(jì)數(shù)法表示而已。

廢話說(shuō)完,這就出現(xiàn)了幾個(gè)問(wèn)題,而且是比較有意思的問(wèn)題。

1?int?i?=?Int32.MaxValue;
2?float?f?=?i;
3?int?j?=?(int)f;
4?bool?b?=?i?==?j;

這里的b,是false。剛才這個(gè)操作,如果我們把float換成long,第一次進(jìn)行隱式轉(zhuǎn)換,第二次進(jìn)行強(qiáng)制轉(zhuǎn)換,結(jié)果將會(huì)是true。乍一看,float.MaxValue是比int.MaxValue大了不知道多少倍的,然而這個(gè)隱式轉(zhuǎn)換中,卻造成了數(shù)據(jù)丟失。int.MaxValue,這個(gè)值等于2^31-1,寫(xiě)成二進(jìn)制補(bǔ)碼形式就是01111…(31個(gè)1),這個(gè)數(shù),在表示成float計(jì)數(shù)的科學(xué)計(jì)數(shù)法的時(shí)候,將會(huì)寫(xiě)成+0.1111…(23個(gè)1)*2^31,對(duì)于那31個(gè)1,里面的最后8個(gè),被float無(wú)情的拋棄了,因此,再將這個(gè)float強(qiáng)制轉(zhuǎn)換回int的時(shí)候,對(duì)應(yīng)的int的二進(jìn)制補(bǔ)碼表示已經(jīng)變成了0111…(23個(gè)1)00000000,這個(gè)數(shù)與最初的那個(gè)int相差了255,所以造成了不相等。
那么提出另一個(gè)問(wèn)題,什么樣的int變成float再變回來(lái),和從前的值相等呢?這個(gè)問(wèn)題其實(shí)完全出在那23位float的數(shù)據(jù)位上了。對(duì)于一個(gè)int,把它寫(xiě)成二進(jìn)制形式之后,成為了個(gè)一32個(gè)長(zhǎng)度的0、1的排列,對(duì)于這個(gè)排列,只要第一個(gè)1與最后一個(gè)1之前的間距,不超過(guò)23,那么它轉(zhuǎn)換成float再轉(zhuǎn)換回來(lái),兩個(gè)值就會(huì)相等。這個(gè)問(wèn)題是與大小無(wú)關(guān)的,而且這個(gè)集合在int這個(gè)全集下并不連續(xù)。

1?double?d?=?0.6;
2?float?f?=?(float)d;
3?double?d2?=?f;
4?bool?b?=?d?==?d2;

這里的b,也是false。剛才這個(gè)操作,如果開(kāi)始另d等于0.5,結(jié)果就將會(huì)是true。乍一看,0.6這個(gè)數(shù)這么短,double和float都肯定能夠表示,那么轉(zhuǎn)換過(guò)去再轉(zhuǎn)換回來(lái),結(jié)果理應(yīng)相等。其實(shí)這是因?yàn)槲覀冇檬M(jìn)制思考問(wèn)題太久了,如果我們0.6化成二進(jìn)制小數(shù),可以發(fā)現(xiàn)得到的結(jié)果是0.10011001……(1001循環(huán))。這是一個(gè)無(wú)限循環(huán)小數(shù)。因此,不管float還是double,它在存儲(chǔ)0.6的時(shí)候,都無(wú)法完全保存它精確的值(計(jì)算機(jī)不懂分?jǐn)?shù),呵呵),這樣的話由于float保存23位,而double保存52位,就造成了double轉(zhuǎn)化成float的時(shí)候,丟失掉了一定的數(shù)據(jù),非再轉(zhuǎn)換回去的時(shí)候,那些丟掉的值被補(bǔ)成了0,因此這個(gè)后來(lái)的double和從前的double值已經(jīng)不再一樣了。
這樣就又產(chǎn)生了一個(gè)問(wèn)題,什么樣的double轉(zhuǎn)換成float再轉(zhuǎn)換回來(lái),兩個(gè)的值相等呢?其實(shí)這個(gè)問(wèn)題與剛才int的那個(gè)問(wèn)題驚人的相似(廢話,都和float打交道,能不相似么),只不過(guò)我們還需要考慮double比f(wàn)loat多了3位的指數(shù)位,太大的數(shù)double能表示但float不行。
還有一個(gè)算是數(shù)學(xué)上的問(wèn)題,什么樣的十進(jìn)制小數(shù),表示成二進(jìn)制不是無(wú)限小數(shù)呢?這個(gè)問(wèn)題可以說(shuō)完全成為數(shù)學(xué)范疇內(nèi)的問(wèn)題了,但是比較簡(jiǎn)單,答案也很明顯,對(duì)于所有的最后一位以5結(jié)尾的十進(jìn)制有限小數(shù),都可以化成二進(jìn)制的有限小數(shù)(雖然這個(gè)小數(shù)可能長(zhǎng)到?jīng)]譜)。
最后,一個(gè)有意思有問(wèn)題,剛才說(shuō)過(guò)0.6表示成為二進(jìn)制小數(shù)之后,是0.1001并且以1001為循環(huán)節(jié)的無(wú)限循環(huán)小數(shù),那么在我們將它存成浮點(diǎn)數(shù)的時(shí)候,一定會(huì)在某個(gè)位置將它截?cái)?#xff08;比如float的23位和double的52位),那么真正存在內(nèi)存里的這個(gè)二進(jìn)制數(shù),轉(zhuǎn)化回十進(jìn)制,到底是比原先的十進(jìn)制數(shù)大呢,還是小呢?答案是It depends。人計(jì)算十進(jìn)制的時(shí)候,是四舍五入,計(jì)算機(jī)再計(jì)算二進(jìn)制小數(shù)也挺簡(jiǎn)單,就是0舍1入。對(duì)于float,要截?cái)喑蔀?3位,假如卡在24位上的是1,那么就會(huì)造成進(jìn)位,這樣的話,存起來(lái)的值就比真正的十進(jìn)制值大了,如果是0,就舍去,那么存起來(lái)的值就比真正的十進(jìn)制值小了。因此,這可以合理的解釋一個(gè)問(wèn)題,就是0.6d轉(zhuǎn)換成float再轉(zhuǎn)換回double,它的值是0.60000002384185791,這個(gè)值是比0.6大的,原因就是0.6的二進(jìn)制科學(xué)計(jì)數(shù)法表示,第24位是1,造成了進(jìn)位。

到了這里,仍然有一事不解,就是對(duì)于浮點(diǎn)數(shù),硬件雖然給予了計(jì)算上的支持,但是它與十進(jìn)制之間的互相轉(zhuǎn)換,到底是如何做到的呢,又是誰(shuí)做的呢(匯編器還是編譯器)。這個(gè)東西突出體現(xiàn)在存在內(nèi)存里的數(shù)明顯實(shí)際與0.6不等,但是無(wú)論哪種語(yǔ)言,都能夠在Debug以及輸入的時(shí)候,將它正確的顯示成0.6提供給用戶(hù)(程序員),最好的例子就是double和ToString方法,如果我寫(xiě)double d=0.59999999999999999999999999999,d.ToString()給我的是0.6。誠(chéng)然,對(duì)于double來(lái)說(shuō),我寫(xiě)的那個(gè)N長(zhǎng)的數(shù)與0.6在內(nèi)存里存的東西是一樣的,但是計(jì)算機(jī),又如果實(shí)現(xiàn)了將一個(gè)實(shí)際與0.6不相等的數(shù)變回0.6并顯示給我的呢?關(guān)于這個(gè)問(wèn)題,歡迎大家討論并請(qǐng)高手指教一二。

轉(zhuǎn)載于:https://www.cnblogs.com/wodehuajianrui/archive/2009/03/18/1415173.html

總結(jié)

以上是生活随笔為你收集整理的int, float, double之间不得不说的故事的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。