我正在使用一种生成大于Extended
类型允许的数字的算法,这会导致运行时错误。
var
a, b, magn: Extended;
...
a := -3,6854775808e-3109;
b := 2,3020377564e+3549;
magn:= a * a + b * b; //EInvalidOp, "invalid floating point operation"
我该如何解决这个问题?
我正在将算法SmbPitchShift Site http://www.dspdimension.com c + +写入pascal。如果有人在Pascal中使用它,我会感谢
答案 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
算法来表达算法。
答案 1 :(得分:0)
如果我理解正确,问题就是例外,而不是溢出。逻辑解决方案是使用基于SSE2的数学,它允许饱和而不是溢出。 (如果有东西溢出,它会改变为类型中最高的有效数字)
据我所知,Delphi目前不支持SSE2代码生成或内部函数,可以在更高级别的语言中实现这一点。
但是由于64位Delphi迫在眉睫,而且x86_64通常比FPU更喜欢SSE2,这可能会在短期内发生变化。