3

我想运行具有周期性边界条件的粒子模拟 - 为简单起见,让我们假设一个区域为 length 的一维模拟1.0。我可以使用以下简短片段强制执行这些条件:

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 )是的,我读过这篇文章,所以我知道为什么它不符合我的要求,也不应该这样做。我的问题不是关于这个,而是关于做什么。

4

2 回答 2

4

你可以使用%这个轻微的修改x = (x + 1.0) % 1.0

于 2013-10-30T10:18:55.550 回答
0

最好的方法可能是从值本身中减去值的下限。计算符合 IEEE 标准的浮点余数是相当复杂的,除非一个系统可以检测和加速“简单情况”,尤其是那些除数是 2 的幂的情况,否则一对if语句很容易更快。

不过,考虑一下为什么 fmod 被设计成令人讨厌的方式可能会很有趣:如果 fmod 被设计为返回一个介于 0 和被除数之间的值,那么当被除数是非常小的正数时结果的精度将是比被除数是非常小的负数时的精度要好得多(精度将限制为除数的精度)。使 fmod 的精度相对于零对称的优势可能超过了结果为非负的优势,但这并不意味着 IEEE 是设计范围限制函数的唯一好方法。

结合 IEEE 方法和零除数方法的优点的另一种方法是指定 mod 函数必须产生一个结果,其数值(对于 d 为正数)小于 的数值d/2,但不小于-d/2。这样的定义将始终产生可以在源操作数类型中表示的结果(如果 D 是一个非常小的值,使得 D/2 不能精确表示,则模数的范围将是对称的)。不幸的是,我知道没有以这种方式工作的库 mod 函数。

于 2013-11-26T19:47:06.240 回答