![]() |
1
3
应用 half-angle formula 因为正弦允许解决问题中提到的影响精度的两个问题:
将其替换为原始公式将导致此中间表示:
通过对术语的简单重新排序,可以得到所需的公式形式:
与原始公式一样,这只需要对两个比例因子进行一次预计算,即 2··sin(incr/2) 和 罪(罪) . 对于小的增量,两者都很小:保持完全的精度。 对于如何将fma应用于此计算,有两种选择。可以通过取消使用一次调整的方法来最小化操作次数,而使用两次,希望fma操作(一次四舍五入两次操作)减少的舍入误差能够补偿精度损失:
另一种方法是将一个fma应用于改进的公式,尽管目前尚不清楚这两个乘法中的哪一个应映射到fma中的无边界乘法:
下面的脚手架通过生成许多( 基础 , 英克思 )然后,在收集生成的所有正弦和余弦值的错误时,为每个值迭代一组步骤。由此计算出 root-mean square error 对于每个测试用例,分别为正弦和余弦。最后报告了在所有生成的测试用例中观察到的最大rms误差。
测试脚手架的输出表明,最快的基于fma的备选方案优于问题中的朴素方法,而更准确的基于fma的备选方案是所考虑的备选方案中最准确的:
|
![]() |
2
1
如果您希望在长时间的迭代计数中获得最大的精度,则可以在从以前的精确值生成增量结果时,以增量方式计算精确值,而不产生累积错误。 例如,如果预先计算 sin(增量*2^x) 和 cos(增量*2^x) 对于 x=6…三十一 ,例如,然后可以使用角度和公式计算每个 iNCR=64×N 输出前64个值时,一次一位。 每64个值都会丢弃增量生成的结果,而使用正确的结果,因此错误不会在长时间内累积。 另外,由于您只需要从任何精确的基中获得64个增量结果,因此可以预先计算直接从基中计算这些结果所需的64个正弦和余弦,而不是以前的结果。 |
![]() |
3
0
可以按以下方式重新排列sin(base+incr)和cos(base+incr)的方程:
这里我们用公式 (1-cos(x)/sin(x)=tan(x/2) , 看见 here ,例如。 现在还不明显的是,这会导致比其他方法更准确的结果, 但在实践中,它非常有效,我们稍后将看到这一点。 同样,这需要两个比例因子的一次性预计算 罪(罪) 和 谭(英克思/ 2) . 在c语言中,我们可以用4个fma-s编写公式:
完整更新的测试代码在这个答案的末尾。
用
新的解决方案
修改测试代码:
|
![]() |
Fyodor · 在C中使用sin和cos计算数学表达式不正确? 11 月前 |
![]() |
Cjmarkham · 基于已知斜边和相邻的[闭合]获得θ 1 年前 |
![]() |
Quiche31 · 符号反三角函数并不总是返回期望的分数 1 年前 |
![]() |
Jack Wild · 三名JS直接在摄像机前获得地面位置 7 年前 |
![]() |
urukh · Arduino波发生器 7 年前 |
![]() |
Michael K. · 如何以java度求反余弦 7 年前 |