与数学库 sin 相比,sin 函数不准确
Posted
技术标签:
【中文标题】与数学库 sin 相比,sin 函数不准确【英文标题】:sin function not accurate compared to math lib sin 【发布时间】:2014-11-01 23:13:03 【问题描述】:我一直在尝试实现一个快速但更重要的是准确的自定义 sin 函数(我不能在我的项目中使用 math.h sin)。当涉及到这种数学时,我不是专家,所以和我一起工作 XD。在网上搜索了一下后,我发现了以下代码,该函数在某些情况下返回的结果不准确。
float SinF(float X)
float Sine;
if (X < -3.14159265F) X += 6.28318531F;
else if (X > 3.14159265F) X -= 6.28318531F;
if (X < 0)
Sine = 1.27323954F * X + .405284735F * X * X;
if (Sine < 0) Sine = .225F * (Sine *-Sine - Sine) + Sine;
else Sine = .225F * (Sine * Sine - Sine) + Sine;
else
Sine = 1.27323954F * X - 0.405284735F * X * X;
if (Sine < 0) Sine = .225F * (Sine *-Sine - Sine) + Sine;
else Sine = .225F * (Sine * Sine - Sine) + Sine;
return Sine;
例子:
Bad result example 1:
Value Passed: 1.57079637
Returned Value: 0.999999881
Correct Value: 1.00000000
Bad result example 2:
Value Passed: 1.76704633
Returned Value: 0.980933487
Correct Value: 0.980804682
Bad result example 3:
Value Passed: 1.96329641
Returned Value: 0.924392164
Correct Value: 0.923955679
任何帮助将不胜感激。
【问题讨论】:
docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html 这已经足够精确了。您可以用精度换取速度,所以就这样。 最好显示X
范围内的相对误差,并确定可接受的相对误差。
@iccthedral 实际上,我需要 sin 来处理图像格式,所以精度比速度更重要。
【参考方案1】:
sin
和 this SO question 中的朋友有很多潜在的实现,但通常归结为一些常用方法:
还有(很多)其他方法,但这些是我见过的更常见的方法。
还要注意浮点的固有精度限制(如 user657267 linked 到)。例如,1.57079637
不完全是 pi/2
,因此它的 sin()
可能不完全是 1。事实上,您列出的所有“正确”值并不完全准确。您必须确定对于您的应用程序来说,准确度有多好。
【讨论】:
在 32 位编译模式下,我在 _asm 关键字中使用处理器代码 fsin,但 _asm 关键字在 64 位模式下不可用,所以我还需要一个函数来实现这一点。我发布的正确值来自 math.h sin 函数,所以这就是我需要的准确性。我试过泰勒级数的罪,因为这似乎是网络上最常见的。我试试 CORDIC。float
只有大约 7 个有效数字,所以您只是看到了基本类型的准确度的限制。如果您需要更高的准确性,请考虑改用double
。
另请注意,您的原始代码看起来可能是泰勒级数,但可能为了优化而进行了修改。
double 可能具有更高的精度,但不使用 double 应该不是问题,因为 fsin 和 math.h sin 在我的情况下都使用浮点数并返回所需的值。如果我错了,请纠正我。
AFAIK,math.h 中通常的sin()
使用double
(或long double
)并从float
版本向下舍入。无论哪种方式,这取决于您需要多少精度的具体情况。如果 7 sig-figs 没问题,那么 float
版本可能会很好。以上是关于与数学库 sin 相比,sin 函数不准确的主要内容,如果未能解决你的问题,请参考以下文章