C語(yǔ)言中浮點(diǎn)數(shù)的精度丟失問(wèn)題解決
一 先來(lái)看一段代碼
#include<stdio.h>
int main()
{
double test=0.1;
printf("%.100lf",test);
return 0;
}運(yùn)行結(jié)果:
![]()
直接從現(xiàn)象說(shuō)結(jié)果:精度丟失由于計(jì)算機(jī)二進(jìn)制轉(zhuǎn)化過(guò)程中因?yàn)楸忍匚贿^(guò)多發(fā)生數(shù)據(jù)的截?cái)鄬?dǎo)致的,這個(gè)結(jié)果是可以偏大也可以偏小的。
解釋一下:首先要知道二進(jìn)制轉(zhuǎn)換為十進(jìn)制的基本方法(除二取余法,乘五取余法等等),最好再了解一下浮點(diǎn)數(shù)的存儲(chǔ),這里的0.1就是一個(gè)典型的例子,對(duì)0.1乘五取余是乘不盡的,那么數(shù)據(jù)轉(zhuǎn)化成的二進(jìn)制序列的長(zhǎng)度就會(huì)超出double的范圍。那么多出的數(shù)據(jù)就會(huì)被截?cái)唷?/p>
二 如何解決
如果你想的是徹底讓屏幕顯示出來(lái)的是0.1,那么,你不孤單,我一開(kāi)始也是這樣想的,但是這是不可能的。但是這個(gè)對(duì)我們的實(shí)際意義不大,畢竟有效的區(qū)段還是夠的。
我在這里具體要解決的是兩個(gè)問(wèn)題
(1)浮點(diǎn)數(shù)的大小比較
#include<stdio.h>
int main()
{
double test=0.1;
if(test==(1-0.9))
{
printf("正常");
}
else
{
printf("what!!!");
}
return 0;
}這段代碼會(huì)輸出“what!”。為什么上面已經(jīng)說(shuō)了0.1乘不盡,這里換成0.5是OK的,因?yàn)?.5D用二進(jìn)制表示就是0.1B。每次都考慮乘不盡不煩嗎?
解決方案
引入庫(kù)函數(shù)<float.h>里定義的宏DBL_EPSILON。
![]()
這里后面的一段英文是他是導(dǎo)致x+n!=x的最小值 (n代表EPSILON伊普西隆,x是任意值)
也就是說(shuō),任意一個(gè)比EPSILON小的值,你給一個(gè)數(shù)加上,都不會(huì)改變它的值。
那么,比EPSILON小的值引起的精度丟失都是在我們的允許范圍內(nèi)的
#include<stdio.h>
#include<float.h>
#include<math.h>
int main()
{
double test = 0.1;
if (fabs(test - (1 - 0.9)) < DBL_EPSILON)
{
printf("正常");
}
else
{
printf("what!!!");
}
return 0;
}上圖有兩個(gè)點(diǎn)
1 。在<math.h>下的fabs(a)即取a的絕對(duì)值
想象一根數(shù)軸,他們相減的絕對(duì)值就是他們的距離
2 。 if(fabs(test-(1-0.9)<DBL_EPSILON))
等價(jià)于(test==1-0.9)(當(dāng)然是對(duì)我們 人 而言)
test和(1-0.9)的距離若是小于DBL_EPSILON,那么精度的丟失是在可控范圍內(nèi)的,說(shuō)明他們倆相等
(2)含浮點(diǎn)數(shù)的表達(dá)式和0.0的比較
要先把上面的搞明白。
之所以單獨(dú)說(shuō)這個(gè)問(wèn)題,我是想強(qiáng)調(diào)一個(gè)數(shù)字與零作比較到底應(yīng)該是a<DBL_EPSILON還是a<=DBL_EPSILON,加強(qiáng)一下理解
EPSILON是允許范圍內(nèi)的最小值(回到宏定義后面的解釋),所以這個(gè)等于不可以加,加了說(shuō)明上面的a如果等于EPSILION時(shí),會(huì)導(dǎo)致數(shù)值的改變。
想要徹底解決精度丟失,是不可能的,也沒(méi)必要,但我們有辦法用近似來(lái)解決。
如果看完這篇文章你還是很迷糊,但我還是想說(shuō)這是不能徹底解決的(我一開(kāi)始也有這種想法),那么希望下次我準(zhǔn)備出的數(shù)據(jù)的存取能對(duì)你有幫助。篇幅太長(zhǎng)了,所以刪刪減減還是準(zhǔn)備放到下次。
總結(jié)
到此這篇關(guān)于C語(yǔ)言中浮點(diǎn)數(shù)的精度丟失問(wèn)題解決的文章就介紹到這了,更多相關(guān)C語(yǔ)言浮點(diǎn)數(shù)精度丟失內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言實(shí)現(xiàn)清空指定文件夾中所有文件的方法
這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)清空指定文件夾中所有文件的方法,實(shí)例分析了C語(yǔ)言實(shí)現(xiàn)文件刪除的相關(guān)技巧,需要的朋友可以參考下2015-06-06
C語(yǔ)言實(shí)現(xiàn)手寫JSON解析的方法詳解
JSON(JavaScript?Object?Notation)是一種輕量級(jí)的數(shù)據(jù)交換格式,用來(lái)傳輸屬性值或者序列性的值組成的數(shù)據(jù)對(duì)象。本文將利用C語(yǔ)言實(shí)現(xiàn)手寫JSON解析,感興趣的可以了解一下2022-09-09
C語(yǔ)言中qsort函數(shù)的用法實(shí)例詳解
這篇文章主要介紹了C語(yǔ)言中qsort函數(shù)的用法實(shí)例詳解的相關(guān)資料,希望通過(guò)本文能幫助到大家,讓大家理解掌握這部分內(nèi)容,需要的朋友可以參考下2017-10-10
C語(yǔ)言調(diào)用攝像頭實(shí)現(xiàn)生成yuv未壓縮圖片
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言如何調(diào)用攝像頭實(shí)現(xiàn)生成yuv未壓縮圖片,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以參考一下2023-11-11
使用map實(shí)現(xiàn)單詞轉(zhuǎn)換的實(shí)例分析
本篇文章是對(duì)使用map實(shí)現(xiàn)單詞轉(zhuǎn)換的代碼實(shí)例進(jìn)行了纖細(xì)的分析介紹,需要的朋友參考下2013-05-05
C語(yǔ)言單鏈隊(duì)列的表示與實(shí)現(xiàn)實(shí)例詳解
這篇文章主要介紹了C語(yǔ)言單鏈隊(duì)列的表示與實(shí)現(xiàn),對(duì)于研究數(shù)據(jù)結(jié)構(gòu)與算法的朋友來(lái)說(shuō)很有參考借鑒價(jià)值,需要的朋友可以參考下2014-07-07

