float為什么不能直接用==作比較

本文嘗試著將以下內(nèi)容做一個淺顯的解釋,主要包括浮點數(shù)為什么是不精確的,浮點數(shù)為什么不能用==和祷嘶!=直接比較俗他,以及浮點數(shù)的比較方法等幾個方面脖捻。如果那個地方說的不對還請各位看官不吝賜教!歡迎大家評論區(qū)討論兆衅。

IEEE 754 --- 二進制浮點數(shù)算術(shù)標(biāo)準(zhǔn)

浮點格式是一種數(shù)據(jù)結(jié)構(gòu)地沮,用于指定包含浮點數(shù)的字段嗜浮,這些字段的布局及其算術(shù)解釋。自計算機發(fā)明以來摩疑,出現(xiàn)了許多種不同的浮點數(shù)表達方式危融,目前最通用的是IEEE二進制浮點數(shù)算是標(biāo)準(zhǔn)-IEEE 754.

IEEE 754規(guī)定了四種表示浮點數(shù)值的方式:單精確度(32位)、雙精確度(64位)雷袋、延伸單精確度(43比特以上吉殃,很少使用)與延伸雙精確度(79比特以上,通常以80位實現(xiàn))楷怒。只有32位模式有強制要求蛋勺,其他都是選擇性的。大部分編程語言都有提供IEEE浮點數(shù)格式與算術(shù)率寡,但有些將其列為非必需的迫卢。例如,IEEE 754問世之前就有的C語言冶共,現(xiàn)在有包括IEEE算術(shù)乾蛤,但不算作強制要求(C語言的float通常是指IEEE單精確度,而double是指雙精確度)捅僵。

二進制如何表示浮點數(shù)的

所有的數(shù)據(jù)在計算機內(nèi)都已二進制形式表示家卖,那么浮點數(shù)的在計算機內(nèi)是如何以二進制形式存儲的呢?

二進制浮點數(shù)是以符號數(shù)值表示法的格式存儲——浮點數(shù)由三部分組成:符號(sign部分庙楚,表示符號0正上荡,1負數(shù)),指數(shù)(exponent部分馒闷,表示指數(shù)位)酪捡,和尾數(shù)(fraction部分,表示有效數(shù)字纳账,大于等于1逛薇,小于2)。
單精度浮點數(shù)來說疏虫,sign占1位永罚,exponent部分占8位,fraction部分占23位卧秘。
雙精度浮點數(shù)來說呢袱,sign占1位,exponent部分占11位翅敌,fraction部分占52位羞福。

那么該如何理解上面這段話呢?舉例來說蚯涮,十進制的5.0坯临,寫成二進制是101.0焊唬,相當(dāng)于1.01×2^2。那么看靠,按照上面那段話赶促,可以得出符號位sign為0,fraction部分為1.01挟炬,exponent部分為2鸥滨。

二進制十進制相互轉(zhuǎn)換

先介紹一下轉(zhuǎn)換采用的規(guī)則:

  1. 二進制轉(zhuǎn)十進制規(guī)則:

R進制轉(zhuǎn)換成十進制:基數(shù)為R的數(shù)字,只要將各個數(shù)字與它的權(quán)相乘谤祖,其積相加婿滓,和數(shù)就是十進制數(shù)。

  1. 十進制轉(zhuǎn)二進制規(guī)則:

整數(shù)部分:正整數(shù)轉(zhuǎn)成二進制粥喜。要點一定一定要記住哈:除二取余凸主,然后倒序排列,高位補零额湘。
小數(shù)部分:小數(shù)部分的轉(zhuǎn)換規(guī)則:十進制小數(shù)轉(zhuǎn)換成二進制小數(shù)采用"乘2取整卿吐,順序排列"法。具體做法是:用2乘十進制小數(shù)锋华,可以得到積嗡官,將積的整數(shù)部分取出,再用2乘余下的小數(shù)部分毯焕,又得到一個積衍腥,再將積的整數(shù)部分取出,如此進行纳猫,直到積中的小數(shù)部分為零婆咸,如果得不到零就截取達到所要求的精度就可以。 然后把取出的整數(shù)部分按順序排列起來芜辕,先取的整數(shù)作為二進制小數(shù)的高位有效位尚骄,后取的整數(shù)作為低位有效位。

例1: 把二進制數(shù)110.0101轉(zhuǎn)換為十進制數(shù):

110.0101=12^2+121+0*20+02^(-1)+12(-2)+0*2(-3)+1*2^(-4)=6.3125

例2: 把十進制數(shù)8.125轉(zhuǎn)換成二進制數(shù):

整數(shù)部分:
13 = 1000物遇,
小數(shù)部分:
0.125x2 = 0.25, 整數(shù)位是0->1000.0;
0.25x2 = 0.5, 整數(shù)位是0->1000.00;
0.5x2 = 1, 整數(shù)位是1->1000.001;

所以8.125 轉(zhuǎn)換成二進制是1000.001

例3: 把十進制數(shù)0.1轉(zhuǎn)換為二進制數(shù)。

0.1x2 = 0.2, 整數(shù)位是0 -> 0.0;
0.2x2 = 0.4, 整數(shù)位是0 -> 0.00;
0.4x2 = 0.8, 整數(shù)位是0 -> 0.000;
0.8x2 = 1.6, 整數(shù)位是1 -> 0.0001;
0.6x2 = 1.2, 整數(shù)位是1 -> 0.00011;
0.2x2 = 0.4, 整數(shù)位是0 -> 0.000110;
...

得到一個無限循環(huán)的二進制小數(shù)憾儒,顯然用有限的字長是無法表示0.1的询兴。告訴你一個悲傷的消息0.2,0.4起趾,0.6诗舰,0.8,0.3训裆,0.7眶根,0.9都是無法精確表示的蜀铲。只有0.5可以用二進制精確表示。拿這些無法精確表示的數(shù)該怎么辦呢属百?我們在十進制轉(zhuǎn)二進制的規(guī)則里說過记劝,如果沒有得到0,就截取達到所要求的精度就可以族扰。由此可知厌丑,一個十進制小數(shù)要能用二進制浮點數(shù)精確表示,最后一位必須是5.當(dāng)然這是必要條件渔呵,并非充分條件怒竿。由此可以看出,一個十進制數(shù)能否用二進制浮點數(shù)精確便是扩氢,關(guān)鍵在于小數(shù)部分耕驰。

float比較方法

不可將浮點變量用“==”或“!=”做直接比較录豺,而應(yīng)該設(shè)法轉(zhuǎn)化成能用“>=”或“<=”作比較的形式朦肘。由上可知計算機在處理浮點數(shù)的時候是有誤差的,所以判斷兩個浮點數(shù)是不是相同巩检,是要判斷是不是落在同一個區(qū)間的厚骗,這個區(qū)間就是 [-EPSINON,EPSINON] EPSINON一般很小,10的-6次方以下兢哭,這個值肯定是越小越精確领舰,不過也看具體的個情況,夠用就好迟螺。

  1. float與“零值”比較
    一般情況我們會定義一個很小的接近于0的值比如0.00001或者更小的冲秽,然后浮點數(shù)跟這個數(shù)作比較。

假設(shè)x是一個浮點數(shù):
const float EPSINON = 0.00001;
if ((x >= - EPSINON) && (x <= EPSINON)
或者
if( abs(a-b) < FLT_EPSILON)

  1. float與float比較

假設(shè)x矩父,y是兩個浮點數(shù)是否相等:
const float EPSINON = 0.00001;
if( abs(a-b) <= EPSINON )

還有一種方法就是擴大再取整锉桑,比如4.113、4.114窍株,直接比較有可能為 false民轴,但是都擴大一千倍,然后強制轉(zhuǎn)換為 int 類型球订,再用 == 比較就可以了后裸。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市冒滩,隨后出現(xiàn)的幾起案子微驶,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件因苹,死亡現(xiàn)場離奇詭異苟耻,居然都是意外死亡,警方通過查閱死者的電腦和手機扶檐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進店門凶杖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蘸秘,你說我怎么就攤上這事官卡。” “怎么了醋虏?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵寻咒,是天一觀的道長。 經(jīng)常有香客問我颈嚼,道長毛秘,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任阻课,我火速辦了婚禮叫挟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘限煞。我一直安慰自己抹恳,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布署驻。 她就那樣靜靜地躺著奋献,像睡著了一般。 火紅的嫁衣襯著肌膚如雪旺上。 梳的紋絲不亂的頭發(fā)上瓶蚂,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天,我揣著相機與錄音宣吱,去河邊找鬼窃这。 笑死,一個胖子當(dāng)著我的面吹牛征候,可吹牛的內(nèi)容都是我干的杭攻。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼疤坝,長吁一口氣:“原來是場噩夢啊……” “哼兆解!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起卒煞,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤痪宰,失蹤者是張志新(化名)和其女友劉穎叼架,沒想到半個月后畔裕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體衣撬,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年扮饶,在試婚紗的時候發(fā)現(xiàn)自己被綠了具练。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡甜无,死狀恐怖扛点,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情岂丘,我是刑警寧澤陵究,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站奥帘,受9級特大地震影響铜邮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜寨蹋,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一松蒜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧已旧,春花似錦秸苗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽巩趁。三九已至宠进,卻和暖如春塔淤,著一層夾襖步出監(jiān)牢的瞬間腰奋,已是汗流浹背阳堕。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工木羹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留好渠,地道東北人脱拼。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓文虏,卻偏偏與公主長得像侣诺,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子氧秘,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容