在過去的幾周里,我被 Matlab 中的浮點比較問題折磨著。
我的代碼涉及大量a<b或c<=d。讓我發瘋的是
dw = 0.001;
W1 = [0:dw:1];
W2 = [0:dw:1];
然后我們有
>>W1(418) = 0.417000000000000
>>W2(418) = 0.417000000000000
>>W1(418)>=W2(418)
ans =
logical
0
>>W2(418)>=W1(418)
ans =
logical
1
我目前處理這個問題的方法是定義一個錯誤項eps0 = 10^(-15)。然后,每當我希望擁有 時a<=b,我都會這樣做a<=b eps0。
但我想知道是否有更通用的方法來解決這個問題?對此,我真的非常感激!
uj5u.com熱心網友回復:
不,浮點數比較沒有通用的方法來解決,每種情況都不一樣,預期的舍入誤差會隨著情況而變化。
而不是使用eps0 = 10^(-15),使用eps(b):a<=b eps(b)。b eps(b)是下一個可以表示的較大值(假設b為正)。這應該處理一種形式的舍入誤差。如果舍入誤差累積,則需要更大的邊距:a<=b 10*eps(b)例如。
uj5u.com熱心網友回復:
這就是你告訴我們你所做的,在我的 R2018a 版本中,事情按預期進行:
>> version
ans =
'9.4.0.813654 (R2018a)'
>> dw = 0.001;
>> W1 = [0:dw:1];
>> W2 = [0:dw:1];
>> W1(418)>=W2(418)
ans =
logical
1
>> W1(418) = 0.417000000000000;
>> W2(418) = 0.417000000000000;
>> W1(418)>=W2(418)
ans =
logical
1
>> W2(418)>=W1(418)
ans =
logical
1
所以我強烈懷疑還有一些你沒有告訴我們的事情。我可以看到得到你的結果的一種方法是如果底層向量不是相同的型別,那么 0.417 的分配會以不同的方式轉換。例如,假設 W1 實際上是單型別而不是雙型別。然后你會得到這樣的結果:
>> dw = 0.001;
>> W1 = single([0:dw:1]);
>> W2 = [0:dw:1];
>> W1(418) = 0.417000000000000; % converted to closest SINGLE PRECISION bit pattern
>> W2(418) = 0.417000000000000; % converted to closest DOUBLE PRECISION bit pattern
>> W1(418)>=W2(418)
ans =
logical
0
>> W2(418)>=W1(418)
ans =
logical
1
>> sprintf('%.60f\n',W1(418))
ans =
'0.416999995708465576171875000000000000000000000000000000000000
'
>> sprintf('%.60f\n',W2(418))
ans =
'0.416999999999999981792342396147432737052440643310546875000000
'
所以這里的兩個數 W1(418) 和 W2(418) 實際上是不同的,因為一個存盤為單精度浮點數,另一個存盤為雙精度浮點數。0.417 到二進制 IEEE 浮點位模式的轉換在兩者之間是不同的。單位模式的值比雙位模式略小,結果是完全可以解釋的。
那么......你的 W1 和 W2 向量實際上是不同的型別嗎?我懷疑它們是,這會質疑您所有的比較邏輯。正如其他人已經指出的那樣,浮點算術結果通常必須謹慎對待,并非常仔細地進行比較(公差等)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/350376.html
