浮点精度和物理计算

Vit*_*meo 2 c# floating-point physics

物理世界中的引力Vector2是(0; 0.1).

已知数字0.1是有问题的,因为"它不能准确表示,但是大约是1.10011001100110011001101×2-4".

拥有重力的这个值给了我碰撞的问题,并产生了非常讨厌的错误.将值更改为0.11可解决这些问题.

有没有更优雅的解决方案,根本不需要改变价值?


这个bug的视频

http://www.youtube.com/watch?v=bRynch1EtnE


源代码

http://pastebin.com/jNkqa3sg

第一种方法(AABBIsOverlapping)检查两个AABB实体之间的交集.每帧为每个主体调用第二个方法(Update).

我将尝试解释Update方法的工作原理:

  1. 将重力加速度矢量添加到速度矢量
  2. 创建临时矢量(下一个)并将其设置为速度
  3. 在当前正文周围的单元格中获取空间哈希中的实体
  4. 如果存在水平重叠,请解决它,将next.X和velocity.X设置为0并移动播放器
  5. 如果存在垂直重叠,请解决它,将next.Y和velocity.Y设置为0(或设置为0.1以防止从天花板不断跳跃)并移动播放器
  6. 循环之后,如果没有重叠,则移动播放器

Geo*_*ett 6

总之没有.通常的解决方案是永远不检查相等性,并始终检查范围+ - epsilon(非常小的值).

  • 从不检查平等是否有点强烈.有时您希望这样做,但如果您测试的值是浮点计算的结果则不会.这是一个不错的建议,但很不清楚它是OP问题的根本原因. (2认同)

Cod*_*aos 5

在物理学中,无法表示一个数字根本不重要。物理学中唯一重要的是舍入误差的累积。

我认为您的问题与不正确的 epsilon 比较有关,甚至与没有 epsilon 的比较有关。但没有更多信息,我无法帮助你。如果您的代码无法处理小的舍入错误,则它是有缺陷的,需要修复。

你可以使用Decimal你的数学代码,它可以0.1m准确地表示。但我认为这不是您真正需要的,因为您的问题很可能与0.1无法在float.


我在您的代码中看到的一个潜在问题是,在解决冲突时,您将身体准确地移出到碰撞边界。也许您需要将其进一步移出一个 epsilon。

  • 这是误导性的,因为可表示性显然与手头的问题无关,但由于 OP 有这种误解,您提供了一种延长它的方法。 (2认同)