1

我正在开展一个模拟空间物理/重力的项目,其中一部分是预测轨道并显示某些信息,其中之一是近点和远点(轨道的最近和最远点)。实现这一点的最简单方法是找到轨道中物体相对于静止物体的接近速度为 0 的点,但由于每秒的计算量有限,几乎不会发生该值恰好为 0 - 所以我的如果当前值的符号和循环之前的值发生了变化,我们的想法是比较每个循环。

代码与此类似:

ArrayList orbit = new ArrayList();    
orbit.Add(newValue);

//In case the sign changes - to +

if(
   orbit.Count >= 2 &&
   physics.getVelocity(orbit[orbit.Count-1], otherObject) == Math.Abs(physics.getVelocity(orbit[orbit.Count-1], otherObject) &&
   physics.getVelocity(orbit[orbit.Count-2], otherObject) != Math.Abs(physics.getVelocity(orbit[orbit.Count-2], otherObject)
)

//In case the sign changes + to -

if(
   orbit.Count >= 2 &&
   physics.getVelocity(orbit[orbit.Count-1], otherObject) != Math.Abs(physics.getVelocity(orbit[orbit.Count-1], otherObject) &&
   physics.getVelocity(orbit[orbit.Count-2], otherObject) == Math.Abs(physics.getVelocity(orbit[orbit.Count-2], otherObject)
)

但有时它似乎不起作用,所以我调试了变量并且找不到任何错误,总是出现以下模式:

Value (1): -0.4523452
Value (2): 1.2435235

或者

Value (1): 0.4523452
Value (2): -1.2435235

但是该算法忽略了一些事件,但据我观察,只有当数字接近 0(如上)但它看起来像这样时:

Value (1): 64.904534
Value (2): -7.3456800

很好,我不知道为什么。我希望有人可以帮助我 - 如果还有任何问题,请询问:)

4

3 回答 3

5

这种检测,要检测一个值为负而另一个为正(顺序无关),您应该使用以下Math.Sign方法:

if (Math.Sign(a) != Math.Sign(b)) { ... }

但是,@supercat 的答案对于您当前的代码是正确的,浮点值这样就很挑剔。

于 2013-06-14T18:42:26.850 回答
4

使用浮点数时,通常应该假设每个计算都可以添加一些小的但任意的 fudge 因子,并且即使在看起来应该执行相同的两个计算序列并累积相同的 fudge 因子的情况下,他们不会总是这样做。完全有可能,如果一个测试Math.Abs(x+y+z) == x+y+z,参数Math.Abs的计算将与等式运算符符号右侧的计算略有不同。

如果要测试一个数字是否小于零,请不要将其与其绝对值进行比较。检查它是否小于零。将计算结果存储在一个变量中,将该变量传递给Math.Abs,并比较是否相等可能比在相等运算符的两侧重复计算更可靠(无论计算产生的任何软糖因素都应该存储在该变量中) ,但何苦呢?

于 2013-06-14T18:31:25.553 回答
0

您可以尝试仅测试该值是否在某个值 0 内。

让我们epsilon成为宽容。距某个数字小于此距离的值将被视为等于该数字。

然后你可以写一个IsApproximately()谓词:

public static bool IsApproximately(double number1, double number2, double epsilon)
{
    return Math.Abs(number1 - number2) <= epsilon;
}

当您想要比较数字时,它使其更具可读性,例如:

if (IsApproximately(velocity, 0, 0.0001))
{
    // Treat as zero
}
于 2013-06-14T19:08:54.793 回答