2011-08-30 100 views
0

我使用的算法生成的數字大於Extended類型允許的數字,這會導致運行時錯誤。如何計算組件非常大的2向量的大小?

var 
    a, b, magn: Extended; 
... 
a := -3,6854775808e-3109; 
b := 2,3020377564e+3549; 
magn:= a * a + b * b; //EInvalidOp, "invalid floating point operation" 

我該如何解決這個問題?


我寫的算法SmbPitchShift網站http://www.dspdimension.com C + +帕斯卡。如果有人在帕斯卡,我會感謝

+0

你的目標是獲得一個有意義的結果,或者只是爲了讓它溢出到+ Infinity? –

+0

你在這裏問了兩個完全不同的問題。我可以回答的第一個問題。第二個我不能。這就是爲什麼你強烈建議你一次提出一個問題的原因。 –

回答

1

如果你真的想要矢量幅度的平方那麼這是不可能的。這真的是一個溢出。

如果你真的想要的幅度,那麼就可以避免這樣的溢出:

function Magnitude(const a, b: Extended): Extended; 
//calculate Sqrt(a*a + b*b) avoiding overflow 
var 
    x, y: Extended; 
begin 
    x := abs(a); 
    y := abs(b); 
    if x=0.0 then begin 
    Result := y; 
    end else if y=0.0 then begin 
    Result := x; 
    end else if x>y then begin 
    Result := x*System.Sqrt(1.0+Sqr(y/x)); 
    end else begin 
    Result := y*System.Sqrt(1.0+Sqr(x/y)); 
    end; 
end; 

根據我的經驗,使用效率低下,非標Extended型而非Double往往表明有問題你的算法。總是有一種方法可以用Double算法來表達算法。

+0

我認爲它會解決,我正在寫算法SmbPitchShift Site http://www.dspdimension.com C++ pascal。如果有人在Pascal中使用它,我會感謝 – Carl

+1

C++很少使用Extended(通常是long double),而是使用float(Delphi中的Single)或double(Double)。實際上,我發現音調轉換庫的數字相當大。你確定你翻譯得很好嗎? –

+2

smbPitchShift()使用浮點數(除了smbATan2()),所以我懷疑你真的需要這麼大的值。只有atan2使用雙打,你確定你翻譯得對嗎? –

0

如果我正確理解你,問題就是例外,而不是溢出。合乎邏輯的解決方案是使用基於SSE2的數學運算,它允許飽和而不是溢出。 (IOW如果有東西溢出,它會變成該類型中的最高有效數字)

據我所知,Delphi目前不支持SSE2代碼生成或內部函數,這將使得這可以在更高級別的語言中實現。

但是,由於64位德爾福即將出現,而且x86_64通常優於FPU上的SSE2,這可能會在短期內改變。

+0

潛在的問題是翻譯被打破。但是對於這個問題,我的答案是計算mag的方式,根本沒有溢出。 –

+0

給定無限時間,你是對的:_) –