数字溢出时如何进行hypot2(x,y)计算

Tho*_*s O 6 math

我想在16位处理器上进行hypot2计算.

标准配方是c = sqrt((a * a) + (b * b)).这个问题是它输出的大量输入.例如200和250,乘以200*200得到90,000,高于最大有符号值32,767,所以它溢出,如b,数字被加上,结果也可能没用; 由于负的sqrt,它甚至可能发出错误信号.

在我的情况下,我正在处理32位数字,但我的处理器上的32位乘法非常快,大约4个周期.我正在使用dsPIC微控制器.我宁愿不必使用64位数字,因为这会浪费宝贵的内存,毫无疑问会更慢.另外,我只有32位数的sqrt,所以64位数字需要另一个函数.那么当值可能很大时,我如何计算一个hypot?

请注意我只能使用整数数学.使用像浮点数学这样的东西会引起速度,我宁愿避免.我的处理器有一个快速整数/固定点atan2例程,大约130个周期; 我可以用它来计算斜边长度吗?

Pau*_*l R 3

根据您需要的精度,您也许能够避免平方和平方根运算。Rick Lyons 的《理解数字信号处理》中有一个关于此主题的章节(第 10.2 节“高速矢量幅度逼近”,在我的版本中从第 400 页开始)。

近似值本质上是:

magnitude = alpha * min + beta * max
Run Code Online (Sandbox Code Playgroud)

其中 max 和 min 是实部和虚部的最大和最小绝对值,而 alpha 和 beta 是两个常数,选择它们是为了在感兴趣的范围内给出合理的误差分布。这些常数可以表示为 2 次方的分数,以保持算术简单/高效。他在书中建议 alpha = 15/16,beta = 15/32,然后您可以将公式简化为:

magnitude = (15 / 16) * (max + min / 2)
Run Code Online (Sandbox Code Playgroud)

可以使用整数运算实现如下:

magnitude = 15 * (max + min / 2) / 16
Run Code Online (Sandbox Code Playgroud)

当然,我们可以使用移位来进行除法:

magnitude = (15 * (max + (min >> 1))) >> 4
Run Code Online (Sandbox Code Playgroud)

一个象限内的误差为 +/- 5%。

有关此技术的更多信息,请访问:http://www.dspguru.com/dsp/tricks/magnitude-estimator