如何在 16 位 MCU 上用 C 语言实现三阶多项式公式计算

问题描述

这是我第一次发帖,但如果之前有人问过这个问题,我会提前道歉。

由于极小的值或大于 32 位的结果(在 16 位 MCU 上),我一直在努力研究如何在 C 中实现三阶多项式公式。 我使用不同的值,但作为一个例子,我想计算公式中的“Y”:

Y = ax^3 + bx^2 + cx + d = 0.00000012*(1024^3) + 0.000034*(1024^2) + 0.056*(1024) + 789.10

我需要使用 base32 来为 "a" = 515 获取有意义的值 如果我乘以 1024^3(10 位 ADC),则会得到非常大的 1,073,741,824

我尝试将它们拆分为“术语 A、B、C 和 D”,但由于每个术语的分辨率不同以及我的 16 位 MCU 的限制,我不确定如何将它们合并在一起:

u16_TermA = fnBase32(0.00000012) * AdcMax * AdcMax * AdcMax;

u16_TermB = fnBase24(0.000034) * AdcMax * AdcMax;

u16_TermC = fnBase16(0.056) * AdcMax;

u16_TermD = fnBase04(789.10);

u16_Y = u16_TermA + u16_TermB + u16_TermC + u16_TermD;

/* AdcMax is a variable 0-1024; u16_Y needs to be 16bit */

我很感激有关此事以及如何最好地在 C 中实现这种计算风格的任何帮助。

提前致谢!

解决方法

迈向改进的一步:

ax^3 + bx^2 + cx + d --> ((a*x + b)*x + c)*x + d

它在数值上更稳定,并且倾向于在函数的零附近提供更准确的答案,并且不太可能溢出中间计算。


第二个想法;如果系数保持其在问题中给出的近似相对值,请考虑缩放系数。

N = 1024; // Some power of 2
aa = a*N*N*N
bb = b*N*N
cc = c*N

y = ((aa*x/N + bb)*x/N + cc)*x/N + d

其中 /N 可以通过轮班快速完成。

明智地选择 N(可能是 2**14 以实现高精度避免 32 位溢出),那么整个代码可能只使用整数数学就可以令人满意地完成。

由于 aa*x/N 只是 a*x*N*N,我认为 2**16 的比例效果很好。


第三个想法:

除了缩放之外,通常这样的三次方程可以重写为

// alpha is a power of 2
y = (x-root1)*(x-root2)*(x-root3)*scale/alpha

使用方程的根,而不是 a,b,c。如果方程的起源是某种曲线拟合,这是非常令人满意的。

不幸的是,OP 的方程 roots 有一个复根对。

x1 = -1885.50539
x2 = 801.08603 + i * 1686.95936
x3 = 801.08603 - i * 1686.95936

...在这种情况下代码可以使用

B = -(x1 + x2);
C = x1 * x2;
y = (x-x1)*(x*x + B*x + C)*scale/alpha

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...