python浮點數表示專題及常見問題 - CSDN

2021-01-10 CSDN技術社區

浮點數用來存儲計算機中的小數,與現實世界中的十進位小數不同的是,浮點數通過二進位的形式來表示一個小數。在深入了解浮點數的實現之前,先來看幾個 Python 浮點數計算有意思的例子:

0.1 == 0.10000000000000000000001

True

0.1+0.1+0.1 == 0.3

False

IEEE 浮點數表示法

這些看起來違反常識的「錯誤」並非 Python 的錯,而是由浮點數的規則所決定的,即使放到其它語言中結果也是這樣的。要理解計算機中浮點數的表示規則,先來看現實世界中十進位小數是如何表示的:

1.234 = 1 + 1/10 + 2/100 + 3/1000

可以用下面的公式來表示:

$$d = \sum_{i=-n}^m10^i*d_i$$

其中 $d_i$ 是十進位中 0~9 的數字。而如果是一個二進位的小數:

1.001 = 1 + 0/2 + 0/4 + 1/8

可以用下面的公式來表示:

$$d = \sum_{i=-n}^m2^i*d_i$$

其中 $d_i$ 是二進位中的 0 或 1。Python 中的浮點數都是雙精度的,也就說採用 64 位來表示一個小數,那這 64 位分別有多少用來表示整數部分和小數部分呢?根據 IEEE 標準,考慮到符號位,雙精度表示法是這樣分配的:

$$d = s * \sum_{i=-52}^{11} 2^i*d_i$$

也就是說用1位表示符號位,11位表示整數部分,52位表示小數部分。正如十進位中我們無法精確表示某些分數(如10/3),浮點數中通過 d1/2 + d2/4 + ... 的方式也會出現這種情況,比如上面的例子中,十進位中簡單的 0.1 就無法在二進位中精確描述,而只能通過近似表示法表示出來:

(0.1).as_integer_ratio()

(3602879701896397, 36028797018963968)

也就是說 0.1 是通過 3602879701896397/36028797018963968 來近似表示的,很明顯這樣近似的表示會導致許多差距很小的數字公用相同的近似表示數,例如:

(0.10000000000000001).as_integer_ratio()

(3602879701896397, 36028797018963968)

在 Python 中所有這些可以用相同的近似數表示的數字統一採用最短有效數字來表示:

print(0.10000000000000001)

0.1

浮點數運算

既然有些浮點數是通過近似值表示的,那麼在計算過程中就很容易出現誤差,就像最開始的第二個例子一樣:

a = .1 + .1 + .1

b = .3

print(a.as_integer_ratio())

print(b.as_integer_ratio())

print(a == b)

(1351079888211149, 4503599627370496)

(5404319552844595, 18014398509481984)

False

為了解決運算中的問題,IEEE 標準還指定了一個捨入規則(round),即 Python 中內置的 round 方法,我們可以通過捨入的方式取得兩個數的近似值,來判斷其近似值是否相等:

round(a, 10) == round(b, 10)

True

當然這種捨入的方式並不一定是可靠的,依賴於捨入的選擇的位數,位數太大,就失去了 round 的作用,太小,就會引入別的錯誤:

print(round(a, 17) == round(b, 17))

print(round(0.1, 1) == round(0.111, 1))

False

True

Python 中使用更精確的浮點數可以通過 decimal 和 fractions 兩個模塊,從名字上也能猜到,decimal 表示完整的小數,而 fractions 通過分數的形式表示小數:

from decimal import Decimal

a = Decimal(0.1)

b = Decimal(0.1000000000000001)

c = Decimal(0.10000000000000001)

print(a)

print(b)

print(c)

a == b == c

0.1000000000000000055511151231257827021181583404541015625

0.10000000000000010269562977782697998918592929840087890625

0.1000000000000000055511151231257827021181583404541015625

False

from fractions import Fraction

f1 = Fraction(1, 10) # 0.1

print(float(f1))

f3 = Fraction(3, 10) # 0.3

print(float(f3))

print(f1 + f1 + f1 == f3)

0.1

0.3

True

總結

浮點數這些奇特的特性讓我們不得不在使用的時候格外注意,尤其是當有一定的精度要求的情況下。如果真的是對精度要求較高且需要頻繁使用浮點數,建議使用更專業的 SciPy 科學計算包。

相關焦點

  • python的int類型專題及常見問題 - CSDN
    在以前的Python2中,整型分為int和long,也就是整型和長整型, 長整型不存在溢出問題, 即可以存放任意大小的數值,理論支持無限大數字。因此在Python3 中,統一使用長整型,用int表示,在Python3中不存在long,只有int。
  • python 卡方專題及常見問題 - CSDN
    其根本思想就是在於比較理論頻數和實際頻數的吻合程度或擬合優度問題。(更多參考:卡方檢驗、卡方分布) 不講過多理論,主要使用 python 實現卡方驗證。之前對於元素/特徵/屬性 異常值的選擇情況,可以使用直方圖、箱型圖、Z分數法等篩選。
  • python卡方分析專題及常見問題 - CSDN
    其根本思想就是在於比較理論頻數和實際頻數的吻合程度或擬合優度問題。(更多參考:卡方檢驗、卡方分布) 不講過多理論,主要使用 python 實現卡方驗證。之前對於元素/特徵/屬性 異常值的選擇情況,可以使用直方圖、箱型圖、Z分數法等篩選。
  • python時間序列平穩性檢驗專題及常見問題 - CSDN
    由於樣本信息太少,如果沒有其他的輔助信息,這種數據結構通常是沒有辦法分析的,但序列平穩性就可以有效解決這個問題。在了解了時間序列的平穩性之後,我們再來詳細講解一下如何用python來進行檢驗。用python來進行平穩性檢驗主要有3種方法,分別是時序圖檢驗、自相關圖檢驗以及構造統計量進行檢驗。首先來說時序圖檢驗,時序圖就是普通的時間序列圖,即以時間為橫軸,觀察值為縱軸進行檢驗。
  • python 卡方檢驗專題及常見問題 - CSDN
    1、先用python展示如何進行卡方檢驗,用上面所舉的例子。# python3.6 import numpy as npfrom scipy.stats import chi2_contingencycontingency_table = np.array([[631,364,582], [154,55,45]])Chi2, P, degree_of_freedom, contingency_table0
  • python一元線性回歸分析專題及常見問題 - CSDN
    python多重線性回歸分析多重線性回歸分析定義多重線性回歸模型:Mulitiple Linear Regression多元線性回歸模型:MultivariateLinear Regression數據準備#多重線性回歸#數據準備import pandas as pddf=pd.read_csv('e:/python/out/corr.csv',encoding='utf8')df根據預測目標,確定自變量和因變量#多重線性回歸
  • 浮點數在計算機中是如何表示的
    float f = 8.25f;int i = *(int*)&f;IEEE浮點表示IEEE浮點標準用的形式近似表示一個數。並且將浮點數的位表示劃分為三個欄位:符號(sign)s決定這個數是負數(s=1)還是正數(s=0)。可以用一個單獨的符號s直接編碼符號s。
  • Python實現一個類似range函數的浮點數生成器 - python高手養成
    那麼,需求來了,我們能否實現一個類似range(start, end, step)函數的浮點數生成器。思路是這樣的:自定義一個類,添加其屬性start、end、step,分別表示浮點數起始值、結束值、步長值。
  • python教程之python數學運算
    中進行分數(fraction)運算分數運算是python中的一個模塊(module)。模塊是由別人寫的,並且可以被拿來直接使用的代碼程序,包括類、函數以及標籤的定義,是python標準函數庫的一部分。使用是必須先插入模塊。
  • python平穩性檢驗專題及常見問題 - CSDN
    3、白噪聲檢驗'''acorr_ljungbox(x, lags=None, boxpierce=False)函數檢驗無自相關lags為延遲期數,如果為整數,則是包含在內的延遲期數,如果是一個列表或數組,那麼所有時滯都包含在列表中最大的時滯中boxpierce為True時表示除開返回LB統計量還會返回Box和Pierce的Q統計量
  • 「python學習手冊-筆記」003.數值類型
    各種進位的表示python的整數默認採用十進位進行表示. 同樣,也支持二進位,八進位,十六進位的表示.這是由於浮點數是有限的比特位數,導致無法精確的表示某些數值.這個問題不僅在python中存在,在其他語言中同樣存在. 不過python有分數和小數,可以很好的規避這些問題. 畢竟python適合科學計算的特性不是白來的.python中的除法python中有三種風格的除法和兩種除法運算符.
  • python 顯著性水平專題及常見問題 - CSDN
    反而是一個大的RSS和一個小的SSE表示一個很好的模型。Total Sum of Squares (TSS):觀測值與觀測值的均值的差的平方和,大概就是訓練集的方差。它是一個數字用來告訴我們數據的總方差中模型的方差的佔比:前面提到一個低的SSE和一個高的RSS表示一個很好的模型擬合,這個R-Squared就表示了這個意思,介於0到1之間,R2越大越好,1最好。
  • 卡方檢驗結果分析專題及常見問題 - CSDN
    簡單統計之後,得到總數和死亡率:此處需要使用到ggbarstats函數,其參數可謂是非常的多,詳細的參數表我放在另一個博客中了,有興趣的朋友可以去看看(https://blog.csdn.net/m0_45248682/article/details/104086729)。
  • 你確定你真的學了Python?
    不就是0.1嘛」但是如果你用 python 去執行一下,會發現結果跟你想的不太一樣,如下圖:>>> 1.1 - 10.10000000000000009這樣大家是不是發現了什麼問題?是的,浮點數在運算過程中並沒有保證完全精確,是什麼原因導致了這種現象呢?
  • arduino設置串口模式專題及常見問題 - CSDN
    默認SERIAL_8N1表示8個數據位,無校驗位,1個停止位。返回值:無。2、關閉串口Serial.end()描述:禁止串口傳輸。此時串口Rx和Tx可以作為數字IO引腳使用。原型:Serial.end()參數:無。返回值:無。
  • 今天學Python第三課常用的數據類型有三種字符串,整數,浮點數
    比如上一關的print(1314)這就是我們常見的數據類型第二種:整數, 英文為integer, 簡稱int。 Python的整數和我們現實數學中定義的一樣:整數是正整數、零和負整數的統稱。說白了,就是沒有小數點的數字。
  • 平穩性檢驗結果分析專題及常見問題 - CSDN
    這裡以Python為例:#pythonimport numpy as npfrom statsmodels.tsa.stattools import adfullerss = np.random.randn(10000)adfuller(ss)#(-100.04436307924058,#
  • f檢驗 matlab專題及常見問題 - CSDN
    15.71985 15.91986 15.71987 16.71988 15.31989 16.11990 16.2MATLAB實現參考網上多個代碼可得https://www.ilovematlab.cn/thread-246993-1-1.htmlhttps://blog.csdn.net
  • 卡方檢驗相關性專題及常見問題 - CSDN
    所以,我們可以定義一個表示X, Y 相互關係的數字特徵,也就是協方差,即:那麼有一個問題:協方差數值大小是否代表了相關程度呢?也就是說如果協方差為 100 是否一定比協方差為 10 的正相關性強呢?假如X1、Y1 和 X2、Y2 分別聯合分布圖,如下所示:
  • Python編程常見問題與解答
    答:如果是Windows系統的話,可以使用瀏覽器打開https://www.lfd.uci.edu/~gohlke/pythonlibs/下載合適版本的whl文件,然後離線安裝。答:代碼可以運行表示沒有語法錯誤,不代表沒有邏輯錯誤。遇到這種情況時,仔細檢查代碼的邏輯和問題的要求是否一致,是否把>寫成>=了,或者忽略了range()函數返回的是左閉右開區間了,是不是把運算符**寫成*了,是不是代碼縮進有錯誤。