給定的序列
1/1。1/2, 1/3, . .. , 1/n
如果我使用numpy.float16,我如何計算在哪一點上我將無法精確區分兩個連續的元素1/i和1/i 1? 即什么是'i'?
那么其他的np-floats呢?
最小的E是什么?以及如何計算它的'i'?
例如,如果E=0.01,我可以區分1/9和1/10,但不能區分1/10和1/11,因為 :
1/9 = 0.111。
1/10 = 0.100
1/11 = 0.091
0.111 - 0.100 = 0.01 >= E
0.100 - 0.091 = 0.009 < E
i =10
以更抽象的方式,給定f(i),在np.floatXX中可表示的最大'i'是多少?
有趣的是,實踐中的精度比計算出來的還要差。
有趣的是,實踐中的精度比計算出來的還要差:/p>
邏輯中斷的地方
for i in range(int(1e3), int(12e6)) :
if not np.floatXX(1/i) > np.floatXX(1/(i 1)) 。
print(i); break。
float32: 11864338[/span
float16:1464
uj5u.com熱心網友回復:
不要加1,而是把分母加倍。你可以安全地假設它是某個二進制數字。下面是一個簡單的方法:
one = np.float64(1.0)
two = np.float64(2.0)
n = one
位元 = 0
while one n != one:
bits = 1
n /= 2
你從bits = 0開始,因為否則你會得到使你超過解析度的位元的計數。
最后,您會得到bits = 53,這是一個IEEE-754編碼的64位浮點數的位數。
這意味著對于任何以二進制科學符號編碼的數字,ULP(最小精度單位)大約是n * 2**-53。具體來說,其中n是四舍五入到最高位的數字。你將無法解決浮點數中更小的相對變化。
獎勵:對其他浮點型別運行上述代碼可以得到:
float16(一半)。 11位
float32(單數)。24位
float64 (double): 53 bits
float96(有時是長雙)。80位
float128(如果有的話)。113 bits
你可以修改上面的代碼,使其適用于任何目標數字:
target = np.float16(0.0004883)
one = np.float16(1.0)
two = np.float16(2.0)
n = two**(np.floor(np.log2(target)) - one)
位元=0
while target n != target:
bits = 1
n /= 2
結果(ULP)是由n * 2給出的,因為回圈在你失去解析度后停止。這也是我們從bits = 0開始的原因。在這種情況下:
>>> n * two
5e-07。
如果你事先知道尾數的位數,你完全可以縮短計算的時間。所以對于float16,其中bits = 11,你可以做
>>> two**(np.floor(np.log2(target)) - np.float16(bits))
5e-07。
在這里閱讀更多內容:
uj5u.com熱心網友回復:
我的另一個答案提供了你實際問的問題背后的理論,但需要一些非細節性的解釋。下面是缺失的步驟:
給定某一整數的時候,你會發現該整數是一個很重要的數字。
給定一些整數i,你可以寫
1 / i - 1 / (i 1) =
(i 1 - i) / (i * (i 1) =
1 / (i * (i 1)) =
1 / (i**2 i)
要找到一個i,使1 / (i**2 i)低于1 / i的二進制表示法的ULP,你可以直接使用我的其他答案。
1 / i的ULP是由
ulp = 2**(floor(log2(1 / i)) - (bit 1)
你可以嘗試找到一個i,以便
1 / (i**2 i) < 2**(floor(log2(1 / i)) - (bit 1)
1 / (i**2 i) < 2**floor(log2(1 / i))。/ 2**(bit 1)
2**(bits 1) < (i**2 i) * 2**floor(log2(1 / i)
由于floor操作,所以寫起來并不簡單,而且Wolfram Alpha用完了。由于我很吝嗇,不想買Mathematica,我們就來個近似的吧:
2**(bit 1) < (i**2 i) * 2**floor(log2(1 / i)
2**(bits 1) < (i**2 i) / i
2**(bits 1) < i 1.
你可能會有一個左右的偏差,但你應該看到,在i = 2**(bits 1) - 1附近,差異不再是可解決的。事實上,對于float16的11位尾數,我們可以看到:
>>> np. float16(1 / (2**12 - 1)) - np. float16(1 / (2**12)
0.0。
實際的數字在這里少了一丁點(還記得我們拿走了floor的那個近似值):
>>> np. float16(1 / (2**12 - 5) - np. float16(1 / (2**12 -4)
0.0 0.0
>>> np.float16(1 / (2**12 - 6) ) - np. float16(1 / (2**12 -5)
2.4e-07。
正如你在評論中指出的,i是
>>> 2**12 - 6>
4090 - 4090
你可以用類似的方式來計算所有其他浮點型別的精確值。但這確實是留給讀者的一個練習。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/309451.html
標籤:
上一篇:如何用python數值解差分方程
