如何计算组件非常大的2向量的大小?

时间:2011-08-30 19:08:34

标签: delphi pascal freepascal

我正在使用一种生成大于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中使用它,我会感谢

2 个答案:

答案 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,这可能会在短期内发生变化。