c - 如何解释反三角函数(和 sqrt)函数(在 C 中)的浮点运算中的舍入误差?

标签 c floating-point trigonometry math.h sqrt

我有一个相当复杂的函数,它采用几个 double 值,表示 3 空间形式的两个 vector (幅度、纬度、经度),其中纬度和经度以弧度为单位,以及一个角度。该函数的目的是将第一个 vector 围绕第二个 vector 旋转指定的角度并返回结果 vector 。我已经验证代码在逻辑上是正确的并且可以工作。

该函数的预期用途是用于图形,因此不需要 double ;然而,在目标平台上,采用 float 的 trig(和 sqrt)函数(特别是 sinf、cosf、atan2f、asinf、acosf 和 sqrtf)在 double 上比在浮点上工作得更快(可能是因为计算这些值的指令实际上可能需要一个double;如果传递了 float,则必须将值转换为 double,这需要将其复制到具有更多内存的区域——即开销)。因此,函数中涉及的所有变量都是 double 的。

这里是问题所在:我正在尝试优化我的函数,以便每秒可以调用它更多次。因此,我已将对 sin、cos、sqrt 等的调用替换为对这些函数的浮点版本的调用,因为它们会使总体速度提高 3-4 倍。这几乎适用于所有输入;但是,如果输入 vector 与标准单位 vector (i、j 或 k)接近平行,则各种函数的舍入误差会累积到足以导致稍后调用 sqrtf 或反三角函数(asinf、acosf、 atan2f) 来传递那些勉强在这些函数域之外的参数。

所以,我陷入了困境:要么我只能调用 double 函数并避免这个问题(最终限制为每秒大约 1,300,000 次 vector 运算),要么我可以尝试想出其他办法.最终,我想要一种方法来清理反三角函数的输入以处理边缘情况(对于 sqrt 这样做很简单:只需使用 abs)。分支不是一种选择,因为即使是单个条件语句也会增加如此多的开销,以至于失去任何性能提升。

那么,有什么想法吗?

编辑:有人对我使用 double 运算还是使用浮点运算表示困惑。如果我将所有值实际存储在双倍大小的容器(即 double 类型变量)中,则该函数比将它们存储在浮点大小的容器中要快得多。但是,由于显而易见的原因,浮点精度触发运算比 double 触发运算更快。

最佳答案

基本上,您需要找到一个 numerically stable解决你的问题的算法。这种事情没有通用的解决方案,需要使用诸如 condition number 之类的概念针对您的特定情况来完成。如果个别步骤。如果潜在问题本身是病态的,这实际上可能是不可能的。

关于c - 如何解释反三角函数(和 sqrt)函数(在 C 中)的浮点运算中的舍入误差?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4171239/

相关文章:

c++ - 有限浮点精度和无限谐波信号生成问题

c - 在标准 C 中(不是 C99)在运行时声明数组的大小

c++ - C++中正确使用memset和memcpy初始化字符数组

c++ - 将 float 舍入为 n 位有效数字的 C 例程?

algorithm - 定点 Cholesky 算法的优点

c++ - 为什么浮点值是这个?

physics - 如何为游戏创建 "intercept missile"?

c - 从 C 中的 argv 中读取

c - c 中的 pow(i,4) 给出运行时错误

python - 结果不正确的异常数学?