2011-08-30 77 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

给定无限时间,你是对的:_) –