我正在翻译与PMP相关的一些c ++代码用于态度控制,部分代码使用FLT_EPSILON
。
代码执行以下操作:
while (angle > ((float)M_PI+FLT_EPSILON))
M_PI
很简单,但我不确定FLT_EPSILON
该怎么做。谷歌告诉我:
这是1和最小浮点之间的差异 float类型的数量大于1.它应该是no 大于1E-5。
然而,其他来源陈述了1.192092896e-07F
等值。
我不是100%清楚它为什么被使用。我怀疑这与浮动的粒度有关。因此,如果有人能够澄清它在c ++中尝试做什么,如果这是javascript的一个问题,那么这将非常有用。
我不确定javascript如何处理像这些值这样的内部内容,所以帮助将不胜感激。
作为一个FYI,我正在翻译的代码如下(源自QGroundControl,它是开源的):
float limitAngleToPMPIf(float angle) {
if (angle > -20*M_PI && angle < 20 * M_PI) {
while (angle > ((float)M_PI + FLT_EPSILON)) {
angle -= 2.0f * (float)M_PI;
}
while (angle <= -((float)M_PI + FLT_EPSILON)) {
angle += 2.0f * (float)M_PI;
}
} else {
// Approximate
angle = fmodf(angle, (float)M_PI);
}
return angle;
}
---编辑---
刚才意识到fmodf没有定义。显然它是一个lib函数并执行以下操作:
fmod()函数计算除法的浮点余数 x by y。返回值是x - n * y,其中n是x /的商 y,向零舍入为整数。
答案 0 :(得分:1)
此代码试图将angle
保持在零左右的区间内。
然而,以这种方式管理角度是麻烦的并且需要相当小心。如果没有文档说明正在做什么,为什么,以及涉及的各种错误和规范,那么它就是不正确的。
这种角度减少不可能在长时间的变化序列中准确地保持累积变化,因为M_PI
只是π的近似值。因此,这种减少通常仅对美学或界面效果有用。例如,当一些角度改变时,减小它可以使其不会增长到由于浮点量化或其他会对观看者造成烦扰的计算误差而导致计算结果中可能存在大跳跃的点。因此,将角度保持在零左右的间隔内会使显示效果看起来很好,即使它与实际物理学在长期内所做的不同。
FLT_EPSILON
的选择似乎是任意的。 FLT_EPSILON
对于表示float
格式的精细度非常重要。但是,在M_PI
的幅度上,float
的ULP(最精细的变化)实际上是2*FLT_EPSILON
。此外,JavaScript使用双精度算法执行加法,FLT_EPSILON
格式的double
没有特别重要的意义。我怀疑作者只是选择FLT_EPSILON
因为它是一个方便的“小”数字。我希望代码的工作方式与编写angle > M_PI
时的代码一样,没有修饰,并且(float) M_PI
在其出现的任何地方都被更改为M_PI
。 (添加FLT_EPSILON
可能是为了给系统添加一些滞后,因此它不会频繁地在π附近的值和接近-π的值之间切换。但是,我建议的标准angle > M_PI
,也包括一些相同的效果,虽然数量较少。对于没有经验的浮点运算的人来说,这可能并不明显。)
此外,看起来angle = fmodf(angle, (float) M_PI);
可能是一个错误,因为这会减少模M_PI
而不是2*M_PI
,因此它会向某些角度添加180º,从而产生完全错误的结果
用return fmod(angle, 2*M_PI);
替换整个函数体可能会令人满意。