亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

整數除法總是等于常規除法的下限嗎?

整數除法總是等于常規除法的下限嗎?

料青山看我應如是 2021-09-23 09:43:57
對于大商,整數除法 ( //) 似乎不一定等于常規除法 ( math.floor(a/b))的下限。根據 Python 文檔(https://docs.python.org/3/reference/expressions.html - 6.7),整數的地板除法產生一個整數;結果是將“floor”函數應用于結果的數學除法。然而,math.floor(648705536316023400 / 7) = 92672219473717632648705536316023400 // 7 = 92672219473717628'{0:.10f}'.format(648705536316023400 / 7) 產生 '92672219473717632.0000000000',但小數部分的最后兩位數字應該是 28 而不是 32。
查看完整描述

3 回答

?
慕工程0101907

TA貢獻1887條經驗 獲得超5個贊

您的測試用例中的商不相等的原因是,在這種math.floor(a/b)情況下,結果是使用浮點算法(IEEE-754 64 位)計算的,這意味著存在最大精度。您擁有的商大于 2 53限制,高于該限制的浮點不再精確到單位。

然而,對于整數除法,Python 使用其無限的整數范圍,因此結果是正確的。

另見PEP 238 中的“真除法語義”

請注意,對于 int 和 long 參數,真正的除法可能會丟失信息;這是真正除法的本質(只要語言中沒有有理數)。有意識地使用 long 的算法應該考慮使用//,因為真正的 long 劃分保留不超過 53 位的精度(在大多數平臺上)。


查看完整回答
反對 回復 2021-09-23
?
回首憶惘然

TA貢獻1847條經驗 獲得超11個贊

您可能正在處理太大而無法準確表達為浮點數的整數值。您的數字明顯大于 2^53,這是相鄰浮點雙精度之間的差距開始大于 1 的地方。因此,在進行浮點除法時會損失一些精度。

另一方面,整數除法是精確計算的。



查看完整回答
反對 回復 2021-09-23
?
翻翻過去那場雪

TA貢獻2065條經驗 獲得超14個贊

你的問題是,盡管“/”有時被稱為“真正的除法運算符”并且它的方法名稱是__truediv__,但它對整數的行為不是“真正的數學除法”。相反,它產生的浮點結果不可避免地具有有限的精度。


對于足夠大的數字,即使是數字的整數部分也會出現浮點舍入誤差。當 648705536316023400 轉換為 Python 浮點數(IEEE double)時,它會四舍五入為 648705536316023424 1。


我似乎無法找到有關當前 Python 中內置類型運算符的確切行為的權威文檔。引入該功能的原始 PEP 指出“/”相當于將整數轉換為浮點數,然后執行浮點數除法。然而,在 Python 3.5 中的快速測試表明情況并非如此。如果是,那么下面的代碼將不會產生任何輸出。


for i in range(648705536316023400,648705536316123400):

    if math.floor(i/7) != math.floor(float(i)/7):

        print(i)

但至少對我來說它確實產生了輸出。


相反,在我看來,Python 正在對所顯示的數字進行除法,并將結果四舍五入以適合浮點數。以該程序輸出為例。


648705536316123383 // 7                   == 92672219473731911

math.floor(648705536316123383 / 7)        == 92672219473731904

math.floor(float(648705536316123383) / 7) == 92672219473731920

int(float(92672219473731911))             == 92672219473731904

Python 標準庫確實提供了 Fraction 類型,并且除以 int 的 Fraction 的除法運算符確實執行“真正的數學除法”。


math.floor(Fraction(648705536316023400) / 7) == 92672219473717628

math.floor(Fraction(648705536316123383) / 7) == 92672219473731911

但是,您應該意識到使用 Fraction 類型可能帶來的嚴重性能和內存影響。請記住,分數可以增加存儲需求而不增加數量。


為了進一步測試我的“一個舍入對兩個”的理論,我使用以下代碼進行了測試。


#!/usr/bin/python3

from fractions import Fraction

edt = 0

eft = 0

base = 1000000000010000000000

top = base + 1000000

for i in range(base,top):

    ex = (Fraction(i)/7)

    di = (i/7)

    fl = (float(i)/7)

    ed = abs(ex-Fraction(di))

    ef = abs(ex-Fraction(fl))

    edt += ed

    eft += ef

print(edt/10000000000)

print(eft/10000000000)

并且直接執行除法的平均誤差幅度比首先轉換為浮點數小得多,支持一個舍入對兩個舍入的理論。


1請注意,直接打印浮點數不會顯示其確切值,而是顯示將舍入到該值的最短十進制數(允許從浮點數到字符串再到浮點數的無損往返轉換)。


查看完整回答
反對 回復 2021-09-23
  • 3 回答
  • 0 關注
  • 233 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號