現(xiàn)象
NSNumber *num = @111.11;
float f = num.floatValue;
NSLog(@"%f",f);
打印log,f值為111.110001
NSNumber *num = @11.11;
float f = num.floatValue;
NSLog(@"%f",f);
打印log,f值為111.110000
原因
十進(jìn)制小數(shù)111.11表示成浮點(diǎn)數(shù)為
//雙精度
0100000001011011110001110000101000111101011100001010001111010111
//單精度
01000010110111100011100001010010
- 雙精度
符號位s: 0
指數(shù)位e: 10000000101
有效數(shù)f:1011110001110000101000111101011100001010001111010111
有效數(shù)的整數(shù)部分:101111
有效數(shù)的小數(shù)部分:0001110000101000111101011100001010001111010111 - 單精度
符號位s: 0
指數(shù)位e: 10000101
有效數(shù)f:10111100011100001010010
有效數(shù)的整數(shù)部分:101111
有效數(shù)的小數(shù)部分:00011100001010010
十進(jìn)制小數(shù)11.11表示成浮點(diǎn)數(shù)為
//單精度
01000001001100011100001010001111
- 單精度
符號位s: 0
指數(shù)位e: 10000010
有效數(shù)f:01100011100001010001111
有效數(shù)的整數(shù)部分:011
有效數(shù)的小數(shù)部分:00011100001010001111
比較小數(shù)部分(0.11)
//雙精度
00011100001010010 //單精度 111.11
00011100001010001111 //單精度 11.11
0001110000101000111101011100001010001111010111 //雙精度 111.11
因?yàn)槎M(jìn)制小數(shù)只能準(zhǔn)確表示以2的次方為分母的分?jǐn)?shù),所以十進(jìn)制小數(shù)不能一一對應(yīng)一個二進(jìn)制小數(shù),我們看到十進(jìn)制小數(shù)0.11轉(zhuǎn)換成二進(jìn)制小數(shù)是一個無限小數(shù)。因?yàn)楦↑c(diǎn)數(shù)的有效位數(shù)是有限的,所以我們拿到的是近似等于0.11的二進(jìn)制浮點(diǎn)數(shù)。
單精度浮點(diǎn)數(shù)的有效位數(shù)是23位
· 111.11可提供給小數(shù)部分的位數(shù)是17位
· 11.11可提供給小數(shù)部分的位數(shù)是20位雙精度浮點(diǎn)數(shù)的有效位數(shù)是52位
· 我們借此看一看到0.11更長,更精確一點(diǎn)的二進(jìn)制小數(shù)表示浮點(diǎn)數(shù)默認(rèn)的舍入規(guī)則是向偶數(shù)舍入
· 首先做向上舍入和向下舍入,判斷精度損失,選擇精度損失最小的舍入方式.
· 如果精度損失是一樣的,那么選擇舍入后最低有效位為偶數(shù)的舍入方式.
0001110000101000111101011100001010001111010111 //46位
//舍入至20位
00011100001010001111 //等于十進(jìn)制的0.109999656677246
//舍入至17位
00011100001010010 //等于十進(jìn)制的0.110000610351563
浮點(diǎn)數(shù)的顯示精確到小數(shù)點(diǎn)后6位,也就是我們看到的0.110000和0.110001
結(jié)論
浮點(diǎn)數(shù)能提供越多的有效位數(shù),浮點(diǎn)數(shù)的值就越接近他所表示的值。