[英]matlab, how do i write a statement that will give me time on xaxis from y=0.3
[英](0.3)^3 == (0.3)*(0.3)*(0.3) returns false in matlab?
我試圖理解MATLAB中基本算術運算的舍入誤差,我遇到了以下奇怪的例子。
(0.3)^3 == (0.3)*(0.3)*(0.3)
ans = 0
我想確切地知道如何計算左側。 MATLAB文檔表明,對於整數冪,使用“通過平方取冪”算法。
“矩陣功率。如果p是標量,則X ^ p是功率p的X.如果p是整數,則通過重復平方來計算功率。”
所以我假設(0.3)^3
和(0.3)*(0.3)^2
將返回相同的值。 但這種情況並非如此。 如何解釋舍入誤差的差異?
有趣的是,標量^
似乎是使用pow
實現的,而矩陣^
是使用square-and-multiply實現的。 以機智:
octave:13> format hex
octave:14> 0.3^3
ans = 3f9ba5e353f7ced8
octave:15> 0.3*0.3*0.3
ans = 3f9ba5e353f7ced9
octave:20> [0.3 0;0 0.3]^3
ans =
3f9ba5e353f7ced9 0000000000000000
0000000000000000 3f9ba5e353f7ced9
octave:21> [0.3 0;0 0.3] * [0.3 0;0 0.3] * [0.3 0;0 0.3]
ans =
3f9ba5e353f7ced9 0000000000000000
0000000000000000 3f9ba5e353f7ced9
這可以通過在gdb下運行octave並在pow
設置斷點來確認。
在matlab中也是如此,但我無法真正驗證。
這是一個小測試程序,遵循Apple的Libm-2026
Source/Intel/xmm_power.c
的系統pow()
,在這種情況下:
#include <stdio.h>
int main() {
// basically lines 1130-1157 of xmm_power.c, modified a bit to remove
// irrelevant things
double x = .3;
int i = 3;
//calculate ix = f**i
long double ix = 1.0, lx = (long double) x;
//calculate x**i by doing lots of multiplication
int mask = 1;
//for each of the bits set in i, multiply ix by x**(2**bit_position)
while(i != 0)
{
if( i & mask )
{
ix *= lx;
i -= mask;
}
mask += mask;
lx *= lx; // In double this might overflow spuriously, but not in long double
}
printf("%.40f\n", (double) ix);
}
這打印出0.0269999999999999962252417162744677625597
,這與我在Matlab中得到的.3 ^ 3
和Python中的.3 ** 3
的結果一致(我們知道后者只是調用此代碼 )。 相比之下,對我來說.3 * .3 * .3
得到0.0269999999999999996946886682280819513835
,如果你只是要求將0.027
打印到那么多的小數位,那么你可能得到同樣的東西,因此可能是最接近的雙倍。
所以有算法。 我們可以准確地找出每個步驟中設置的值,但是考慮到執行它的不同算法,它會轉向一個非常小的數字並不太令人驚訝。
感謝@Dougal我發現了這個:
#include <stdio.h>
int main() {
double x = 0.3;
printf("%.40f\n", (x*x*x));
long double y = 0.3;
printf("%.40f\n", (double)(y*y*y));
}
這使:
0.0269999999999999996946886682280819513835
0.0269999999999999962252417162744677625597
這種情況很奇怪,因為使用更多數字的計算會產生最差的結果。 這是因為無論如何,初始數字0.3用幾位數近似,因此我們從一個相對“大”的錯誤開始。 在這種特殊情況下,發生的事情是少數位的計算給出另一個“大”錯誤,但符號相反......因此補償了初始錯誤。 相反,使用更多數字的計算會產生第二個較小的錯誤,但第一個仍然存在。
閱讀Goldberg的“每個計算機科學家應該知道的浮點運算” (這是Oracle的重印)。 明白了。 浮點數不是微積分的實數。 對不起,沒有TL; DR版本可用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.