3D 'shooter'跳跃算法 - C++低级缺陷。两个相同的双打在应该相等的时候并不相等。4.0 != 4.0 显然



可能的重复项:
浮点比较

嗯,这是一个奇怪的问题。通常,以下if( 4.0 == 4.0 ){return true}将始终返回true 。在我拥有的一个简单的小型opengl 3d"射击"程序中,当我尝试添加"跳跃"效果时,情况并非如此。

这个想法相当简单,我有一个三角形条带的地形,当"角色"移动/行走时,你沿着 2d 高度阵列移动,因此你在山丘/低谷的各个高度上上下行走。

drawScene()函数之外(或者如果你知道opengl,glutDisplayFunc()),我有一个update()函数,当角色"跳跃"时上下抬高角色,这在drawScene()中称为。换句话说,我可以解释它的高度,跳跃算法如下:

参数:

double currentJumpingHeight
double maximumJumpingHeight = 4.0
double ypos;
const double jumpingIncrement = 0.1; //THE PROBLEM!!!! HAS TO BE A MULTIPLE OF 0.5!!
bool isJumping = false;
bool ascending = true;

算法:

(when space is pressed) isJumping = true.
if ascending = true and isJumping = true, 
      currentJumpHeight += jumpingIncrement (and the same for ypos)
if currentJumpingHeight == maximumJumpingHeight, //THE PROBLEM
     ascending = false
     (we decrement currentJumpingHeight and start to fall until we hit the ground.)

它非常简单,但它仅在跳跃增量是0.5的倍数时才有效!

如果jumpingIncrement是,比如说,0.1,那么currentJumpingHeight永远不会等于maximumJumpingHeight。角色像火箭一样起飞,永远不会回到地面。即使两个变量打印到标准输出并且相同,条件也永远不会为真。这是我想解决的问题,这是荒谬的。

我不想要任何关于跳跃算法的反馈 - 请只是上面的段落。

请帮忙。

这只是一个典型的浮点精度问题。特别是0.1不能使用二进制浮点精确表示。另一方面,像 0.5 和 0.25 这样的数字可以准确地表示,因此可能会起作用。我相信编译器仍然可以自由地使其不起作用,即使在这种情况下也是如此。

在您的情况下,解决方案正在使用>=

if ascending && (currentJumpingHeight >= maximumJumpingHeight)
     ascending = false
     currentJumpingHeight = maximumJumpingHeight

你也可以使用ε比较,但我尽可能避免它们。在您的情况下,一个简单的>=似乎比 epsilon 相等更干净。

正如人们所说,这是一个典型的浮动精度点问题。看看这个基本上,以同样的方式,您不能以 10 为基数的有限位数 1/3 进行编码

1/3 = 0.3333333333.....

你不能在基数 2 中做 1/10。这将是

0.1 = 0x0.0001100110011001100110011001100110011001100110011...

您永远不应该比较浮点数,但检查差异是否小于值,例如

if (fabs(a-b) < 1e-6)

而不是

if(a==b)

当然,在您的情况下,只需使用">="。

它适用于您的 0.5 增量,因为 0.5 是二进制的 1/2 或 0.1,因此编码正确。这将适用于 2 的任何幂,即 0.5 或 0.125,但不适用于 0.1。

最新更新