可能的重复项:
浮点比较
嗯,这是一个奇怪的问题。通常,以下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。