低估了浮点因素

时间:2014-04-11 18:46:57

标签: c floating-point rounding-error

大多数物理引擎支持执行物体轨迹跟踪,该轨迹将返回介于0.0和1.0之间的因子,表示物体沿物体首先撞击物体的距离。

我关心的问题是,通过轨迹的那个因素移动物体导致其位置超过它应该击中和停止的边界(由于浮点舍入)。

例如,我创建了一个C程序,尝试随机案例,直到遇到这个问题,并提出了这个例子(虽然我经验丰富,运动极少,所以它不是特定于大浮点数):

float start     = 4884361.0f;
float wall      = 37961976.0f;
float end       = 1398674432.0f;
float time      = (wall - start) / (end - start);
float new_pos   = start + time * (end - start);
printf("We hit %f, but moving left us at %f.\n", wall, new_pos);

此案例打印出来:We hit 37961976.000000, but moving left us at 37961980.000000.

因此位置移动到墙壁位置以外,现在物体被卡在墙内。

有没有办法生成因子或执行因子乘法,以便浮点误差总是低于所有可能值的实际值?

1 个答案:

答案 0 :(得分:1)

计算出的值是下一个(或接近下一个)浮点数。我们处于float精度的极限。为了确保答案在预期答案的一侧或在一侧,有许多方法

1)更高的中间精度:(应该更经常地提出正确的答案)

float start     = 4884361.0f;
float wall      = 37961976.0f;
float end       = 1398674432.0f;
double time     = ((double)wall - start) / ((double)end - start);
float new_pos   = start + time * ((double)end - start);

2)逻辑:(这绝对有用)

if (new_pos > wall) new_pos = wall;

3)使用稍微较低的时间值:(温和的黑客)

float new_pos = start + nextafterf(time,0.0f) * (end - start);

4)将FP舍入模式更改为舍入为零:(这可能会产生很大的影响)

fesetround(FE_TOWARDZERO); 

5)一个简单的因素:

static const float factor = 0.99999;
float new_pos = start + factor*time * (end - start);

很多专业人士和缺点是方法。