如下C#代碼
float a = f;
float b = f;
float c = a b;
此時c為多少?
?錯誤!
此時c為!
為什麼?
其根本原因是計算機所使用二進制代碼無法准確表示某些帶小數位的十進制數據
下面我們來分析下
我們知道將一個十進制數值轉換為二進制數值需要通過下面的計算方法
整數部分連續用該整數除以取余數然後商再除以直到商等於為止然後把得到的各個余數按相反的順序排列簡稱除取余法
小數部分十進制小數轉換為二進制小數采用乘取整順序排列法用乘以十進制小數將得到的整數部分取出再用乘余下的小數部分然後再將積的整數部分取出如此進行直到積中的小數部分為或者達到所要求的精度為止然後把取出的整數部分按順序排列起來即先取出的整數部分作為二進制小數的高位後取出的整數部分作為低位有效位簡稱乘取整法
含有小數的十進制數轉換成二進制整數小數部分分別進行轉換然後相加
例如將十進制數值轉換為二進制數值步驟如下
(整數部分)
/=
/=
/=
/=
/=
() =()
(小數部分)
*=
*=
() =()
() =() +() =()
按照上述方法我們將及轉換為二進制代碼
() = ()
() = ()
後面的省略號表示已經算不完了後面在無限重復 這段二進制數值
文章開始部分我們用的float類型下面我們來看看float類型是否能存儲上面轉換出的二進制代碼
目前計算機上存儲浮點數值是按照IEEE(電氣和電子工程師協會)浮點存儲格式標准來存儲的
IEEE單精度浮點格式共位包含三個構成字段位小數f位偏置指數e位符號s將這些字段連續存放在一個位字裡並對其進行編碼其中:位包含位的小數f :位包含位指數e第位包含符號s如下圖所示
也就是說上面將及轉換出的二進制代碼我們只能存儲位即使數據類型為double也只能存儲位這樣大家便能看出問題出現的原因了
截取的二進制代碼已無法正確表示及根據這個二進制代碼肯定無法正確得到結果
如何解決這個問題?知道其根本原因後我們知道是無法從根本上解決這個問題的但我們可以有一些曲線救國的方法下面列舉幾個
因為二進制數值可以准確表示整數(可以使用整數轉換為二進制方法驗證下)所以可以將小數乘以或等變成整數然後做運算最後再通過除以或等獲得結果
通過截取結果的有效小數位數等來取得最好的近似結果然後在做處理
對於可以用有限長度的二進制數值表示的十進制數值可以使用存儲位數大於其長度的數據類型
解決方案正在補充中……若各位有什麼好的方法也可以提出來!
以上解決方案需要按照使用的實際情況來決定使用哪種方法
From:http://tw.wingwit.com/Article/program/net/201311/12845.html