我想运行具有周期性边界条件的粒子模拟 - 为简单起见,我们假设使用长度为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.0
2 。 “模数”版本和“手动”版本输出的几个例子来说明差异:
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 )是的,我读过this post,所以我知道为什么它没有做我想做的事情,那它不应该。我的问题不是关于这一点,而是关于做什么。
答案 0 :(得分:4)
您可以使用%
稍加修改x = (x + 1.0) % 1.0
答案 1 :(得分:0)
最好的方法可能是从值本身中减去值的下限。计算符合IEEE标准的浮点余数是相当复杂的,除非一个系统能够检测并加速“简单情况”,特别是那些除数是2的幂,一对{{1} }语句很快就会更快。
可能有趣的是,考虑为什么fmod被设计成令人讨厌的方式:如果fmod被设计为返回0和被除数之间的值,那么当被除数是一个非常小的正数时结果的精度当被除数是一个非常小的负数时,数字会比精确度好得多(精度将限于除数的精度)。使fmod的精度相对于零的相对对称的优点可能超过了使结果为非负的优点,但这并不意味着IEEE是设计范围限制函数的唯一好方法。
将IEEE方法和零到除法方法的优点结合起来的另一种方法是指定一个mod函数必须产生一个结果,其数值(对于d为正)小于数值。 if
,但不低于d/2
。这样的定义总是会产生在源操作数类型中可表示的结果(如果D是非常小的值,使得D / 2不能精确表示,则模数的范围将是对称的)。不幸的是,我知道没有以这种方式工作的库mod函数。