如何比較兩個浮點數 - 人人焦點

文章推薦指數: 80 %
投票人數:10人

本文主要參考了「浮點數專家」 Bruce Dawson[1] 寫的Comparing Floating Point Numbers, 2012 Edition[2],也推薦他關於浮點數的其他文章[3](最近還一直在更新 )。

人人焦點 影視 健康 歷史 數碼 遊戲 美食 時尚 旅遊 運動 星座 情感 動漫 科學 寵物 家居 文化 教育 故事 如何比較兩個浮點數 2021-02-19IVWEB社區 本文授權轉載自原作者BOTman,未經許可請勿轉載.「夫自細視大者不盡,自大視細者不明。

——《莊子·秋水》比較兩個浮點數是否相等並不是一個簡單的問題:由於浮點數的精度誤差,一般不能使用絕對相等比較;基於絕對誤差的近似相等比較要求使用者對允許的誤差範圍有明確的預期,並不通用;基於相對誤差的近似相等比較看似通用,但又可能會在0附近「栽跟頭」。





本文主要參考了「浮點數專家」BruceDawson[1]寫的ComparingFloatingPointNumbers,2012Edition[2],也推薦他關於浮點數的其他文章[3](最近還一直在更新👍)。

「本文提到的Equals()/AlmostEqualsAbs()/AlmostEqualsRel()/AlmostEqualsUlp()函數的具體實現參考almost_equals.h[4](在線演示[5])👈絕對相等?不靠譜比較兩個數是否相等,最直觀的比較方法就是直接使用==進行比較:f1 == f2  // Equals()根據IEEE754浮點數標準[6],浮點數(其中爲固定的基數,爲符號位,爲尾數,爲指數)表示爲符號位-指數-尾數形式:十進位浮點數(b==10)就是數學中常用的科學計數法(scientificnotation)[7]二進位浮點數(b=2)常用於計算機中的表示和存儲,其中單精度(single-precision)[8]對應32位,雙精度(double-precision)[9]對應64位「在C++中,0.1屬於雙精度浮點數,0.1f屬於單精度浮點數。

爲什麼計算機使用二進位浮點數?因爲基於現有的CPU架構,二進位運算效率更高。

雖然在數學上,實數是 連續的 ——任意十進位數和二進位數可以 相互轉換,它們的浮點數表示形式也可以相互轉換:十進位定點數十進位浮點數二進位定點數二進位浮點數0.125 0.001 0.1 0.000110011...(0011 循環) 但是在計算機中,數值是 離散的 ——有限精度的二進位浮點數 不能準確表示 所有的十進位數(在線轉換工具[10]):十進位數0.1對應的二進位浮點數的尾數ppp是1.100110011...(0011循環)由於32位單精度浮點數的尾數p 只有23位,只能保留小數點後23位(即1.10011001100110011001101)所以,近似表示的二進位數0.000110011001100110011001101約等於十進位數0.10000000149,出現誤差存在問題——有限精度的浮點數轉換近似表示會帶來誤差,而浮點數運算則會放大誤差,所以判斷兩個浮點數(其中至少一個是運算結果)的絕對相等往往是不可靠的:float sum = 0.0f;for (int i = 0; i (0.1f, 0.1) == false);           // expect trueassert(AlmostEqualsAbs(0.1f, 0.1) == false);  // expect trueassert(AlmostEqualsRel(0.1f, 0.1) == false);  // expect trueassert(AlmostEqualsUlp(0.1f, 0.1) == false);  // expect true爲此,可以通過放大允許的誤差,緩解精度丟失的問題:assert(AlmostEqualsAbs(0.1f, 0.1, static_cast(FLT_EPSILON)) ==       true);assert(AlmostEqualsRel(0.1f, 0.1, static_cast(FLT_EPSILON)) ==       true);assert(AlmostEqualsUlp(0.1f, 0.1, FLT_EPSILON / DBL_EPSILON) == true);相反,從高精度轉爲低精度(從double轉爲float)則會抹除細微的誤差:assert(Equals(static_cast(0.1), 0.1f) == true);另外,由於精度的限制,兩個非常接近(相差0ULP)的十進位定點數字面量(literal),只能表示爲相同的二進位浮點數:assert(Equals(67329.234f, 67329.235f) == true);  // expect false寫在最後BruceDawson的總結是「沒有銀彈」[23]——在比較兩個浮點數是否近似相等時,需要根據具體場景,選擇更合適的比較方法:但如果能提前判斷允許的誤差範圍,也可以使用絕對誤差所以,並不存在判斷任意兩個浮點數的通用方法🙃現實世界也一樣——對於有錢的人來說,AlmostEquals(百元鈔票,0)==true對於沒錢的人來說,AlmostEquals(一元硬幣,0)==false最後,11月31日將抽取一名在下方留言的幸運讀者,送出一張瑪莎拉蒂5元代金券🙃Maserati-Voucher(圖片來自網絡)如果有什麼問題,歡迎交流。

😄參考資料[1]BruceDawson:https://randomascii.wordpress.com/[2]ComparingFloatingPointNumbers,2012Edition:https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/[3]關於浮點數的其他文章:https://randomascii.wordpress.com/category/floating-point/[4]almost_equals.h:https://bot-man-jl.github.io/articles/2020/Comparing-Floating-Point-Numbers/almost_equals.h[5]在線演示:https://godbolt.org/z/xofPTx[6]IEEE754浮點數標準:https://en.wikipedia.org/wiki/IEEE_754[7]科學計數法(scientificnotation):https://en.wikipedia.org/wiki/Scientific_notation[8]單精度(single-precision):https://en.wikipedia.org/wiki/Single-precision_floating-point_format[9]雙精度(double-precision):https://en.wikipedia.org/wiki/Double-precision_floating-point_format[10]在線轉換工具:https://www.h-schmidt.net/FloatConverter/IEEE754.html[11]FLT_EPSILON/DBL_EPSILON:https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon[12]ULP(unitinthelastplace):https://en.wikipedia.org/wiki/Unit_in_the_last_place[13]WhatEveryComputerScientistShouldKnowAboutFloating-PointArithmeticbyDavidGoldberg:https://www.itu.dk/~sestoft/bachelor/IEEE754_article.pdf[14]nextafter(1.0f):https://en.cppreference.com/w/cpp/numeric/math/nextafter[15]FLT_EPSILON:https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon[16]符號位-數值(sign-magnitude):https://en.wikipedia.org/wiki/Signed_number_representations#Signed_magnitude_representation[17]+0/-0:https://en.wikipedia.org/wiki/Signed_zero[18]只需要進行整數運算,不涉及任何浮點數運算:https://stackoverflow.com/questions/2550281/floating-point-vs-integer-calculations-on-modern-hardware[19]gtest-internal.h:https://github.com/google/googletest/blob/master/googletest/include/gtest/internal/gtest-internal.h[20]+∞/-∞:https://en.wikipedia.org/wiki/Infinity[21]NaN(notanumber):https://en.wikipedia.org/wiki/NaN[22]gtest_unittest.cc:https://github.com/google/googletest/blob/master/googletest/test/gtest_unittest.cc[23]BruceDawson的總結是「沒有銀彈」:https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ 相關焦點 浮點數的奧祕 來源:公衆號(c語言與cpp編程)1前言我們在學習C語言時,通常認爲浮點數和小數是等價的,並沒有嚴格區分它們的概念,這也並沒有影響到我們的學習,原因就是浮點數和小數是綁定在一起的,只有小數才使用浮點格式來存儲。

PHP中的浮點數 對浮點數進行比較運算是一個坑爹的事,由於栽在這個問題上的次數比較多,總是記吃不記打的,痛定思痛後打算整理一下,避免下次再犯。

浮點數的存儲[轉載] 標準在IEEE-754規範[39]中,浮點數由三部分組成:符號位、指數部分和尾數部分(標準化表示方式)。

單精度浮點數一般是用4字節(32bit)來表示。

不同標準的單精度浮點數、半精度浮點數表示方式[39]數據類型符號位指數部分尾數部分FP321823FP161510bFP16187規格化表示Normalized一個浮點數可以有多種表示方式,比如:1.23×102,0.123×103,12.3×101爲了提高數據的表示精度同時保證數據表示的唯一性,需要對浮點數做規格化處理 漫談計算機組成原理(十)浮點數運算 浮點數和定點數一樣,都是計算機中數據的存儲形式。

定點數我們可以理解成純小數或者純整數,但是實際上在計算機中參與運算的數字並非都是定點數。

比如,有些數據過大,比如2100這樣的數據,如果寫成二進位的形式,寄存器肯定是無法放下的。

於是就有了浮點數這種數據。

本文主要講述浮點數的概念、浮點數的規格化,以及浮點數的各種運算。

Python浮點數的冷知識 兩個元組都只有一個元素(逗號後面沒有別的元素,這是單元素的元組的表示方法,即len(a)==1)。

float()是個內置函數,可以將入參構造成一個浮點數。

爲什麼會這樣呢?前面分享的第一個冷知識就跟「nan」有關,作爲整體,兩個元組相等,但是它們唯一的元素卻不相等。

之所以會這樣,因爲「nan」表示除了數以外的東西,它是一個範圍,所以不可比較。

單片機浮點數的實用快速除法介紹 作爲單片機程式設計師來說,在編寫程序時經常要檢驗程序中的浮點數運算結果是否正確,但手中又沒有合適的檢驗工具,非常麻煩。

在進行除法計算時,通常使用的方法是比較除法,即利用循環移位和減法操作來得到24~32位商,效率很低。

這裡給出一種浮點數除法運算的實用快速算法。

該方法以數值計算中的預估-修正方法爲指導,充分利用了16位單片機的乘除法功能,很輕易地實現了浮點數的除法。

浮點數和定點數的相互轉換 看到浮點和定點一直不知道如何劃分這個概念的範疇。

以爲浮點就是float表示小數,定點就是int可表示整數而已。

經過學習明白了顯然是錯誤的。

應該是這樣劃分的:浮點:小數點非固定的數,可表示數據範圍較廣,整數,小數都可表示。

包含float,double;定點:小數點固定,可表示整數,小數。

浮點數,你真的懂了嗎? 而負數就比較特殊了點,負數在計算機中是以「補碼」表示的,所謂的補碼就是把正數的二進位全部取反再加1,比如-1的二進位是把數字1的二進位取反後再加1,如下圖:所以所以它們的精度在十進位中分別是 log10(2^53) 約等於 15.95 和 log10(2^24)約等於 7.22 位,因此double的有效數字是 15~16 位,float的有效數字是 7~8位,這些是有效位是包含整數部分和小數部分;double的指數部分是11位,而float的指數位是8位,意味著double相比float能表示更大的數值範圍;那二進位小數,是如何轉換成二進位浮點數的呢 Python中的浮點數和小數 在浮點數運算中,總會有誤差的,這一點在下面會顯示出來。

要解決浮點數運算的誤差問題,decimal所創建的小數類型,則是一種比較好的選擇。

float類型用浮點數運算,好處是方便、而且速度快。

浮點數會給出你所聲明的數字的近似值。

c51單片機浮點數及其彙編程序設計 浮點數運算浮點數運算包括加、減、乘、除四則運算,比較運算,開方運算,多項式運算和函數運算。

其它運算都可用這些基本運算的組合來完成。

本節主要介紹浮點數四則運算及其子程序。

1.浮點數的加、減運算浮點數的運算就是求結果的尾數、數符、階碼包括階符的過程。

在加、減運算中,參加運算的浮點數的階碼可能是不同的,其尾數所代表的值也是不同的。

python浮點數表示專題及常見問題-CSDN 浮點數用來存儲計算機中的小數,與現實世界中的十進位小數不同的是,浮點數通過二進位的形式來表示一個小數。

在深入了解浮點數的實現之前,先來看幾個Python浮點數計算有意思的例子:0.1==0.10000000000000000000001True0.1+0.1+0.1==0.3FalseIEEE浮點數表示法這些看起來違反常識的「錯誤」並非Python的錯,而是由浮點數的規則所決定的,即使放到其它語言中結果也是這樣的 PIC單片機的浮點數格式及轉換 在我們設計的儀表中採用PIC系列單片機,碰到了浮點數的運算問題,查閱其有關資料發現,其浮點數的格式及其與十進位數之間的轉換,與我們常用的MCS-51單片機所提供的三字節、四字節浮點數完全不同,本文將說明其浮點數的格式及其與十進位數之間的轉換和程序設計步驟。

15張圖帶你深入理解浮點數 但如果十進位是小數,轉爲二進位小數如何做?採用「乘2取整,順序排列」。

這要回到IEEE754標準關於浮點數的規定。

5、浮點數的IEEE754表示上文提到,浮點數由四個部分構成,那IEEE754標準是如何規定它們的存儲方式的呢? NET5開始支持半精度浮點數Half類型 微軟在.NET5的第7預覽版中加入了一個稱爲Half的類型,相當於半精度浮點數binary16,也就是使用16位元存儲浮點數值。

IEEE754規範定義了各種浮點數類型,包括binary16、binary32、binary64和binary128,微軟提到,C#中相當於binary32的Float,以及binary64的Double,這兩個是大部分開發人員熟悉的類型,這些標準格式可以讓開發者在應用程式中,選擇適當的類型表達一定範圍的精度數值。

基於IEEE754的浮點數存儲格式分析研究 本文對浮點數、IEEE754浮點數的表示方法、規格化處理等進行了分析,重點分析、比較了Intelx86和SPARC結構計算機IEEE754浮點數的存儲格式。

1浮點數在計算機系統的發展過程中,曾經提出過多種方法表示實數,但是到目前爲止使用最廣泛的是浮點表示法。

php浮點數和字符串 有關浮點數的細節1:浮點數不應直接進行大小比較!先看一個現象:可見:浮點數直接進行比較是「不可靠的」。

原因是:浮點數在內存中的二進位形式(最底層的形式),是不精確的,比如:那如果需要(其實這很常見)進行浮點數比較,該怎麼辦?考慮現實應用所需的精度要求的基礎上,來講他們轉換爲整數後進行比較! 二進位浮點數的精度損失,你怎麼看? 與其說我們是驚嘆於「浮點數在內存中竟然會損失精度?!」,倒不如說是還不習慣二進位的世界。

大約就是在說起「(十進位里的)這小數(到了二進位里)怎麼就成無限的(不能被精準表示)了呢」時,會默認省掉括號里的進位數。

關於浮點數的細節問題 1.計算機中浮點數的構成分爲三個部分:符號位,指數位和小數位。

符號位決定了這個浮點數的正負,指數位和小數位決定了這個浮點數的大小。

2.IEEE爲了讓浮點數可以表示所有的情況,所以把浮點數分爲四種情況:規格化、非規格化、無窮大和NaN規格化是爲了表示浮點數的一般情況。

非規格化是爲了表示0和非常接近0的浮點數。

學校里學不到的C語言教程之6:可怕的浮點數 所以他告訴我的知識點都是很真誠的,這其中我印象最深的就是浮點數的問題,坦率地說無論我對他們的看法如何,沒有他告訴我,恐怕其中的問題我要兩三年後才會知道。

這個問題其實他說得非常的簡單:程序里不要使用float,要用double。

這是爲什麼? PHP浮點數的一個常見問題的解答 關於PHP的浮點數,我之前寫過一篇文章: 關於PHP浮點數你應該知道的(All『bogus』aboutthefloatinPHP)



請為這篇文章評分?