在Java中实现周期边界条件的最快方法

3

我希望能够使用周期边界条件运行粒子模拟 - 为了简单起见,我们假设一个长度为1.0的1D模拟区域。我可以使用以下简短的代码片段来强制执行这些条件:

if (x > 1.0)
    x -= 1.0;
if (x < 0.0)
    x += 1.0;

但它感觉很“笨拙”1——特别是当将其推广到更高的维度时。我尝试做了一些类似于

x = x % 1.0;

这段代码对于 x > 1.0 这种情况处理得很好,但是对于 x < 0.02 的情况并不会产生想要的结果。下面是 "取模" 版本和 "手动" 版本输出的一些示例,以展示它们之间的差别:

Value: 1.896440,  mod: 0.896440,  manual: 0.896440
Value: -0.449115, mod: -0.449115, manual: 0.550885
Value: 1.355568,  mod: 0.355568,  manual: 0.355568
Value: -0.421918, mod: -0.421918, manual: 0.578082

1) 对于我目前的应用程序,“笨重”的方法可能已经足够了。但是为了成为更好的程序员,我仍然想学习是否有一种“更好”的(或至少外观更好的)方法来做到这一点。

2) 是的,我已经阅读了这篇文章,所以我知道为什么它不能做我想要的事情,以及它不应该。我的问题不是关于这个,而是关于应该怎么办。


有没有什么原因,不能将if/else语句放在一个方法中,可能会用一个指定边界的字段包装类来作为参数? - chrylis -cautiouslyoptimistic-
@chrylis:这绝对是更好的方法,但仍然感觉有点笨拙。此外,虽然我这次没有特别需要它,但知道一种无分支的高性能应用程序处理方式也是很不错的。 - Tomas Aschan
2个回答

4

您可以使用以下稍作修改的代码x = (x + 1.0) % 1.0来进行操作。


太好了!这正是我在寻找的!=) - Tomas Aschan

0
最好的方法可能是从值本身减去 floor 值。遵守 IEEE 标准计算浮点数余数相当复杂,除非在可以检测和加速“易于处理”的情况,特别是除数是二的幂次方的系统上,一对 if 语句可能会更快。
不过,考虑一下 fmod 设计为烦人的方式的原因可能会很有趣:如果 fmod 设计为返回介于 0 和被除数之间的值,则当被除数是一个非常小的正数时,结果的精度比被除数是非常小的负数时要好得多(精度将受到除数的限制)。fmod 的精度相对于零的平衡优势可能超过了结果为非负数的优势,但这并不意味着 IEEE 是设计范围限制函数的唯一好方式。
一种替代方法将结合 IEEE 方法和零除数方法的优点,就是规定模函数必须产生一个结果,其数值(对于正的 d)小于 d/2 的数值,但不小于 -d/2。这样的定义总是会产生一个可表示源操作数类型的结果(如果 D 是一个非常小的值,使得 D/2 不精确地表示,那么模数的范围将是对称的)。不幸的是,我不知道任何库模函数以这种方式工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接