我正在从零开始制造一个刚体物理引擎(为了教育目的),我想知道我是否应该为它选择单精度或双精度浮动。
我将使用OpenGL来可视化它,并使用glm库在内部计算引擎中的内容以及可视化。约定似乎是在几乎所有地方为OpenGL使用浮点,而glm::vec3和glm::vec4似乎在内部使用float。我还注意到有glm::dvec3和glm::dvec4,但是似乎没有人使用它。我该如何决定使用哪一种呢?double似乎很有意义,因为它在今天的硬件上具有更高的精度和几乎相同的性能(据我所知),但其他所有东西似乎都使用了float ,除了的一些功能和GLFW的一些功能。
发布于 2013-12-10 00:20:57
当然,一般的规则是正确第一,性能第二?这意味着使用double,除非您能够说服自己使用float获得所需的保真度。
要看的是一个位的有效大小--相对于你想要建模的最小的坐标系统。
例如,如果你使用地球坐标,100度工作到1E7米左右。IEEE 754浮点数只有23位精度,因此相对精度只有1E-7。因此,坐标只精确到1米左右。这可能是或不足以解决这一问题。
我从经验中学到,总是使用double进行物理和物理建模计算,但我承认这并不是一个普遍的要求。
当然,这并不意味着呈现应该使用double;您很可能希望将其作为float。
发布于 2017-01-13 09:27:24
我在一个常见的标题中使用了typedef,并使用float作为我的缺省值。
typedef real_t float;我不建议为此使用模板,因为在尝试使用多态/虚拟函数时,它会导致巨大的设计问题。
为什么浮起作用
这些浮标对我来说很好,原因有三个:
首先,几乎每一个物理模拟都需要在作用力和力矩中加入一些噪声,以达到逼真的效果。这种随机噪声的大小通常比浮标的精度大得多。
第二,在许多情况下,精度有限实际上是有益的。考虑到几乎所有经典的刚体力学都不适用于现实世界,因为没有完美的刚体。所以当你把力施加到不太完美的刚体上时,你就不会得到7位数的完美加速度。
第三,许多模拟都是短期的,因此累积的误差仍然足够小。使用双精度不会自动改变这一点。创建与现实世界相匹配的长期运行模拟是非常困难的,这将是一个非常专门的项目。
当浮动不工作时,
以下是我不得不考虑使用双倍的情况。
当双打不能工作
事实上,在双重伤害中,有时会有更高的精度,尽管它很少见。每个计算机科学家都应该知道的..。的一个例子:如果您有一些随时间而收敛到1的量。如果结果为0,则获取它的日志并执行一些操作。当使用double时,您可能永远不会得到1,因为舍入可能不会发生,但是在浮动时可能会发生。
另一个例子:您需要使用特殊代码来比较实际值。这些代码通常有默认舍入到epsilon,对于浮动是相当合理的1E-6,但是对于双倍它的1E-15。如果你不小心,这会给你很多惊喜。
性能
另一个令人惊讶的是:在现代x86硬件上,浮点数与双倍的原始性能几乎没有差别。与浮点类型相比,内存对齐、缓存等几乎占绝对优势。在我的机器上,用浮标对100米随机数进行简单的求和测试需要22秒,而双倍则需要25秒。因此,浮动速度确实快了12%,但我仍然认为它太低了,不能仅仅为了性能而放弃双倍。然而,如果您使用SSE指令或GPU或嵌入式/移动硬件(如Arduino ),那么浮点数将更快,这无疑是驱动因素。
一个物理引擎,除了刚体的直线和旋转运动之外,可以在今天的桌面级硬件单线上以2000 on的频率运行。您可以将其并行化到多个核心。许多简单的低端模拟只需要50 of。在100赫兹时,事情开始变得非常顺利。如果你有PID控制器,你可能要达到500赫兹。但是即使在这种更糟糕的情况下,你仍然可以用足够好的桌面来模拟大量的对象。
总之,除非你实际测量性能,否则不要让性能成为你的驱动因素。
做什么
经验法则是尽可能精确地使用代码工作。对于刚体的简单物理引擎来说,浮子通常是足够好的。但是,您希望能够在不修改代码的情况下改变主意。因此,最好的方法是像在开始时提到的那样使用typedef,并确保您的代码可以同时工作于float和double。然后,经常测量和选择类型,随着您的项目的发展。
在你的情况下,另一件重要的事情是:将物理引擎与渲染系统分离开来。物理引擎的输出可以是双倍的,也可以是浮点的,并且应该被输入到任何渲染系统所需要的。
发布于 2013-12-06 20:03:01
这是简短回答。
Q. Why does OpenGL use float rather than double?
A. Because most of the time you don't need the precision and doubles
are twice the size.另一件需要考虑的事情是,不应该在任何地方都使用double,就像有些事情可能需要使用double而不是float一样。例如,如果你画一个圆圈,通过画一个圆圈的角度,只有那么多的方块显示在屏幕上。它们将重叠,在这种情况下,双倍将毫无意义。然而,如果您正在执行任意浮点算法,如果您试图精确地表示Mandelbrot级数(尽管这完全取决于您的算法),您可能需要额外的精度。
无论哪种方式,如果您打算在绘图中使用这些值,则通常需要回滚到浮动。
https://stackoverflow.com/questions/20432006
复制相似问题