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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

C语言的int, float,double相互转化 (从本质上理解可能的问题)

發(fā)布時(shí)間:2024/4/18 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言的int, float,double相互转化 (从本质上理解可能的问题) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。 https://blog.csdn.net/github_33873969/article/details/78040129

從學(xué)了C語(yǔ)言之后,一直習(xí)慣于C/C++任意的強(qiáng)制轉(zhuǎn)化,但是C語(yǔ)言的強(qiáng)制轉(zhuǎn)化卻總是帶來(lái)意想不到的后果,在這里,我將從int,float,double的本質(zhì)上講解這些可能出現(xiàn)的問題以及解決辦法,在下面你將看到:

OK,現(xiàn)在好戲開始。

  • int
    • unsigned int: unsigned int所進(jìn)行的是模數(shù)計(jì)算,就是正常的二進(jìn)制相加減,計(jì)算方法和十進(jìn)制加減并無(wú)區(qū)別,但是unsigned int有著正溢出和負(fù)溢出的問題,如下圖計(jì)算所示:

      這一點(diǎn)是我們需要注意的地方。
    • int:int所使用的是32位補(bǔ)碼,關(guān)于補(bǔ)碼的運(yùn)算,在這里就不贅述了,大部分計(jì)算機(jī)導(dǎo)論的書籍都有相關(guān)說(shuō)明。
    • 接下來(lái),要說(shuō)的就是unsigned int和int的相互轉(zhuǎn)化,請(qǐng)看如下代碼:
/* WARNING: This is buggy code */ float sum_elements(float a[],unsigned length) {int i;float result=0;for(i=0;i<=length-1;i++){result+=a[i];return result;} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

這段代碼計(jì)算一個(gè)數(shù)組所有元素之和,看起來(lái)似乎沒什么問題。但是當(dāng)你的數(shù)組為空的時(shí)候,length輸入0之后,卻返回一個(gè)存儲(chǔ)器錯(cuò)誤,這是為什么呢?請(qǐng)看上文關(guān)于unsigned int計(jì)算的式子,length是unsigned int 類型,進(jìn)行的是模數(shù)運(yùn)算,只代表正數(shù),如果出先了0000000(這里有32個(gè)0)-00000..01(31個(gè)0,1個(gè)1)=111…11111(32個(gè)1)=UMAX。一個(gè)本該為-1的數(shù)變成了無(wú)符號(hào)數(shù)最大值,當(dāng)然,當(dāng)i取任何不為0的數(shù)都發(fā)生了非法訪問,自然出現(xiàn)了存儲(chǔ)器錯(cuò)誤,并且任何數(shù)都小于UMAX,就會(huì)出現(xiàn)判別式永遠(yuǎn)為真,出現(xiàn)死循環(huán)。解決這個(gè)問題的方法有兩種,做一個(gè)判斷,當(dāng)傳入length<1,直接返回0.或者,在之前就將length轉(zhuǎn)化為int。

  • 浮點(diǎn)數(shù)(float,double的理解)
    • 什么是定點(diǎn)數(shù),定點(diǎn)數(shù)有什么缺點(diǎn):
      我們用二進(jìn)制數(shù)表示整數(shù),我們也想用二進(jìn)制表示小數(shù)。自然而然,我們會(huì)像十進(jìn)制的小數(shù)一樣,在二進(jìn)制上加上小數(shù)點(diǎn),例如1.001111122,

      但是這樣的二進(jìn)制會(huì)出現(xiàn)什么樣的問題呢?請(qǐng)看下面的二進(jìn)制小數(shù)
整數(shù)部分小數(shù)部分二進(jìn)制(Representation)
53/4101.1122

大家觀察一下,二進(jìn)制小數(shù)有什么特點(diǎn)。
只能準(zhǔn)確的表示x/2kx/2k只能近似,請(qǐng)看下面的小數(shù)

十進(jìn)制小數(shù)二進(jìn)制(Representation)
1/30.01010101[01]…22

[0011]表示無(wú)限循環(huán)小數(shù)
為什么會(huì)出現(xiàn)這樣的計(jì)算結(jié)果,請(qǐng)看下面1/3 和 1/5是如何計(jì)算的。

2?2+2?4+2?6.....+2?2n=n=12?2n=limn+14(1?2?2n)1?(2?2)=132?2+2?4+2?6.....+2?2n=∑n=1∞2?2n=limn→+∞14(1?2?2n)1?(2?2)=13

1/5就復(fù)雜了點(diǎn)

2?3+2?4+2?7+2?8+2?11+2?12+.......+21?4n+2?4n=n=121?4n+n=12?4n=limn+18(1?21?4n)1?(2?4)+limn+116(1?2?4n)1?(2?4)=215+115=152?3+2?4+2?7+2?8+2?11+2?12+.......+21?4n+2?4n=∑n=1∞21?4n+∑n=1∞2?4n=limn→+∞18(1?21?4n)1?(2?4)+limn→+∞116(1?2?4n)1?(2?4)=215+115=15

可見,當(dāng)小數(shù)不能表示為

x2k?x2k?
s:表示符號(hào)位,只用一個(gè)bit表示
M:表示尾數(shù)(significand)(frac)也表示小數(shù)位,即能準(zhǔn)確表示小數(shù)位
E:表示指數(shù)位,簡(jiǎn)單來(lái)說(shuō)就是位數(shù)的多大。
那么,我們來(lái)看一下,我們最常用的float,double是怎么組成的:

明顯的看出,float有8位指數(shù)位,23位尾數(shù)位。指數(shù)最大可表示的范圍為-127~126,但浮點(diǎn)數(shù)的指數(shù)計(jì)算有一點(diǎn)技巧要用到:E-Bias。
下面是浮點(diǎn)數(shù)所表示的一個(gè)范圍:

大家可以清楚的看到浮點(diǎn)數(shù)隨著大小的不同被分成好幾種,接近0的被稱為Denormalized,比較大的數(shù)字被分為Infinity,接下來(lái)介紹這幾種數(shù)字的特征:
Normalized:這是最常見的一種情況,指數(shù)位EXP不為0(不小),EXP不全為1(不大)。此時(shí),階碼(這個(gè)2EE-1,k表示指數(shù)位的位數(shù),float單精度即32位浮點(diǎn)為127,double雙精度為1023。故float單精度的E范圍為-126~127,對(duì)于雙精度為-1022~+1023。
而對(duì)于尾數(shù)位,即小數(shù)位:相當(dāng)于得到的數(shù)為1.M(M表示尾數(shù)位)
下面就到了重點(diǎn)了,這也是浮點(diǎn)數(shù)經(jīng)常被大家忽略的地方。
Denormalized:當(dāng)階數(shù)E全為0的時(shí)候,被稱為Denormalized,那么它的指數(shù)位就變成了E=1-Bias, 之所以不用-Bias,而用1-Bias,是為了實(shí)現(xiàn)與Normalized的數(shù)實(shí)現(xiàn)完美過渡,具體如何過渡的圖片會(huì)在下面給出。
而Denormalized的尾數(shù)有什么特點(diǎn)呢:如果frac為0,說(shuō)明該數(shù)為0,但是不知道是+0還是-0。因?yàn)?#xff0c;前面的符號(hào)位未知。如果frac不為0的話,那么實(shí)際的數(shù)字表示為0.M(M為尾數(shù)位),記住,此時(shí)前面是0.,因?yàn)橹挥惺?.最終才能接近0
Infinity:當(dāng)指數(shù)位全為1,frac尾數(shù)位為0的時(shí)候表示Infinity(可以表示無(wú)窮大),分別取符號(hào)位為1或者0,表示正無(wú)窮或負(fù)無(wú)窮。可以滿足Infinity相乘或除,表示溢出。
NaN:not a number,即指數(shù)位全為1,frac尾數(shù)位不全為0.
一張圖可以表示Normailized,Denormalized,Infinity,NaN

這張圖說(shuō)明,從Denormalized到NaN有什么變化:

可以看到在Denormalize使用E=1-Bias,并且M前取0,實(shí)現(xiàn)了從Largest denorm到Smallest norm完美過渡。
- 浮點(diǎn)數(shù)的rounding
上文提到無(wú)論是定點(diǎn)數(shù)還是浮點(diǎn)數(shù)都只能表示有限的位數(shù),那么舍入就顯的是一個(gè)很重要的環(huán)節(jié)了。浮點(diǎn)數(shù)采取的舍入方法,小于一半的向下舍入,大于一半的向上舍入,在中間的,close to even(向偶數(shù)舍入),下面是幾個(gè)二進(jìn)制例子:
Format A:
There are k=3 exponent bits. The exponent bias is 3.
There are n=4 fraction bits.
Format B:
There are k=4 exponent bits. The exponent bias is 7.
There are n=3 fraction bits.
要求給出A,將A轉(zhuǎn)化為B
前一半為A,后一半為B

位值位值
0110000101110001
1011110712712

可以看出第二,三,四的問題的關(guān)鍵在于進(jìn)位
三的A為:0.11001,即到B先轉(zhuǎn)化為1.1001,明顯B的frac只有三位,所有根據(jù)close to even,需要接近偶數(shù),所以,round down:1.100,符合。
比較有問題的是最后一個(gè):000 0001 。首先,000說(shuō)明是Denormalize,則該數(shù)表示為0.0001*2?2?2,由于B是4位exp,所以不會(huì)是最小的數(shù),所以由Denormalize->Normalize,答案也為1/64
為什么要選擇,close to even呢?如果全部的數(shù)字都為0.01要精確到小數(shù)點(diǎn)后一位的話,如果是四舍五入,那么最后的誤差將是0.01*n,但如果是close to even的,認(rèn)為偶數(shù)和奇數(shù)是等概率出現(xiàn),就很小的避免誤差往一邊倒的情況。

  • 浮點(diǎn)數(shù)的計(jì)算
    首先先來(lái)兩個(gè)公式
    x+ff
    但是3.14+(1e10-1e10)=3.14
    le20*(le20-le20)=0.0
    le20*le20-le20*le20=NaN,由于溢出的關(guān)系,可見在數(shù)字大的情況下不滿足加法結(jié)合律和乘法分配律

最后,來(lái)看看double,float和int相互轉(zhuǎn)化可能的問題

判斷以下式子是否正確:

A.正確,因?yàn)閐ouble的frac為32位和int相同,不會(huì)丟失信息。
B.錯(cuò)誤,因?yàn)閒loat的frac為23位小于int,會(huì)丟失信息。
C.錯(cuò)誤。double比f(wàn)loat精度高。從double轉(zhuǎn)float會(huì)丟失信息。
D.正確。
E.正確。符號(hào)數(shù)正負(fù)轉(zhuǎn)化只取決于符號(hào)位。
F.正確。浮點(diǎn)數(shù)在進(jìn)行運(yùn)算的時(shí)候會(huì)全部轉(zhuǎn)化為浮點(diǎn)數(shù)。
G.正確。

H.錯(cuò)誤。如果f+d溢出,結(jié)果為0.

總結(jié)

以上是生活随笔為你收集整理的C语言的int, float,double相互转化 (从本质上理解可能的问题)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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