我目前正在为涉及许多困难数学运算的医疗设备开发固件。目标处理器支持硬件中的浮点运算,但仅支持float32
(aka single
)。
为了模拟行为并证明我的公式和代码的正确性,我已将固件的相关/数学部分移植到 Linux 中的 GCC 工具链(gcc 6.3.0,libc6 2.24),仔细检查float32
无处不在,并且没有使用会降低数学运算的精度或标准兼容性的编译器开关;值得注意的是,没有任何一个-ffast-math
或它的朋友。
现在,事实证明,对于一小组输入参数,我得到了意想不到的结果。我已经找到了这个问题,并得出结论,为(准确地说:)为一组非常小的输入参数libm
计算了错误的结果。arctan
atan2
例如,如果我有
#include <math.h>
#define C_RAD2DEG (57.29577951308f)
int main(void)
{
float f_Temp = C_RAD2DEG * atan2f(0.713114202f, 0.665558934f);
}
f_Temp
被计算为46.9755516f
,正确的结果在哪里46.975548972f
。
请注意,我一般都知道不同浮点数据类型、舍入错误等问题。
然而,我的感觉是,即使考虑到 的低精度,上面显示的误差也太高了一个数量级float32
,不幸的是,对于接下来的计算,这个误差太大了。
此外,只有很小的atan2
函数可能输入参数子集受到问题的影响。
任何人都可以简单地解释一下这是一个错误,libm
还是仅仅是由于计算的不精确float32
和需要大量的顺序操作atan2
?