Java 南的问题

Java 南的问题,java,double,Java,Double,我的代码有问题已经两周了,调试失败。我来这里是希望有人能帮忙。我写了一个程序,利用Barnes-Hut算法进行n体引力模拟。我的问题是一个或多个“粒子”将{NaN,NaN,NaN}的位置分配给它们(使用三个双精度来表示三维空间的x,y,z)。这反过来导致其他粒子的加速度为{NaN,NaN,NaN},反过来,速度和位置也为{NaN,NaN,NaN}。基本上,在一两帧之后,一切都消失了。它似乎发生在updateAC方法中,但我感觉情况并非如此。我明白这是一项巨大的事业,我非常感谢任何帮助我的人。 我

我的代码有问题已经两周了,调试失败。我来这里是希望有人能帮忙。我写了一个程序,利用Barnes-Hut算法进行n体引力模拟。我的问题是一个或多个“粒子”将{NaN,NaN,NaN}的位置分配给它们(使用三个双精度来表示三维空间的x,y,z)。这反过来导致其他粒子的加速度为{NaN,NaN,NaN},反过来,速度和位置也为{NaN,NaN,NaN}。基本上,在一两帧之后,一切都消失了。它似乎发生在updateAC方法中,但我感觉情况并非如此。我明白这是一项巨大的事业,我非常感谢任何帮助我的人。 我查到的是: 没有负平方根,所有的值似乎都在它们的极限范围内。 源代码是可用的。再次感谢

似乎产生NaN的代码:

private static void getAcc(particle particle, node node)
{
    if ((node.particle == null && node.children == null) || node.particle == particle)
    {
        //Geting gravity to a node that is either empty or the same node...
    }
    else if (distance(node.centerOfMass, particle.position) / node.sideLength > theta && node.children != null)
    {
        for (int i = 0; i < node.children.length; i++)
        {
            if (node.children[i] != null)
            {
                getAcc(particle, node.children[i]);
            }
        }
    }
    else
    {
        particle.acceleration = vecAdd(particle.acceleration, vecDiv(getForce(particle.position, particle.mass, node.centerOfMass, node.containedMass), particle.mass));
    }
}
private static double sumDeltaSquare(double[] pos1, double[] pos2)
{
    return Math.pow(pos1[0]-pos2[0],2)+Math.pow(pos1[1]-pos2[1],2)+Math.pow(pos1[2]-pos2[2],2);
}
private static double[] getForce(double[] pos1, double m1, double[] pos2, double m2)
{
    double ratio = G*m1*m2;
    ratio /= sumDeltaSquare(pos1, pos2);
    ratio /= Math.sqrt(sumDeltaSquare(pos1,pos2));
    return vecMul(vecSub(pos2, pos1), ratio);
}
private static double distance(double[] position, double[] center)
{
    double distance = Math.sqrt(Math.pow(position[0]-center[0],2) + Math.pow(position[1]-center[1],2) + Math.pow(position[2]-center[2],2));
    return distance;
}
private static void getAcc(粒子,节点)
{
if((node.particle==null&&node.children==null)| | node.particle==particle)
{
//正在将重力获取到空节点或同一节点。。。
}
else if(距离(node.centerOfMass,particle.position)/node.sideLength>theta&&node.children!=null)
{
for(int i=0;i
我不会调试您的代码。但是NaN值是对浮点数进行数学上无效操作的结果。其中最著名的是除以0(不会引发浮点异常)。 这怎么会发生

如果您的计算产生非常小的数字,它们可能会变得太小,无法表示为64位浮点数字(它们需要的位数比可用的位数多),Java将返回0.0。 在另一个方向上,如果出现溢出(数字的大小需要太多位),Java会将其转化为无穷大。使用无穷大和0进行数学运算可以快速生成NaN,NaN会通过应用于它的每个操作传播


有关详细信息,请参阅Java语言规范的第4.2节和第15.17节。

我不确定这是否是唯一的问题,但这是一个开始

sumDeltaSquare有时会返回0,这意味着在getForce
ratio/=sumDeltaSquare(pos1,pos2)中使用该值时它将产生无穷大并开始引发问题


这是一个严重的问题,您需要调试并弄清楚每件事的含义。不过我很喜欢看这些点。

首先,为什么不使用Java的库?(它作为Java3D的一部分分发。下载Java3D的二进制构建,然后只使用vecmath.jar)您的问题很可能是自定义向量函数中的某个地方。如果不是的话,@pimaster可能是正确的,因为如果两个质量块占据一个空间,那么您的平移量方法
sumDeltaSquare
可能返回
0
。这意味着,除非你在黑洞里,否则你是做错了:P。或者你需要先提出量子引力理论,然后才能进行模拟


如果您不能使用vecmath(即,这是一个家庭作业),我建议您使用a查找
return*
的每个实例,然后将其替换为
assert!Double.isNan(*)和&Double.isFinite(*)\nreturn*
,除了用
*
替换正则表达式找到的任何“匹配组”。我已经完全忘记了那是什么,但我让你开始使用谷歌。我还建议您在拥有工作代码之前避免优化。

当第一个粒子被指定{NaN}坐标时,这些坐标从何而来?发布这段代码将是一个好主意。仅此而已-我还无法找到NaN的实际来源。投票结束:让陌生人通过检查发现代码100行中的错误是没有效率的。您应该使用调试器(或大量打印语句)向后跟踪;当你在坐标被指定给粒子之前打印坐标时,一定有一个计算结果产生了NaN。@danfoster,它们是数字还是NaN?如果它们是NaN,请检查该变量的值来自何处。继续这样做,直到你发现一段代码不符合你的要求。把那段代码贴出来,我们可以帮你。给我一分钟。张贴了似乎给我带来麻烦的东西。抱歉,这篇文章太长了。通常,除0不会导致NaN。对于Java浮点,除0会导致float.NEGATIVE_∞或float.POSITIVE_∞,具体取决于分子的符号。True。我读说明书的速度有点太快了。仅当执行0.0/0.0时,除以0才返回NaN。尽管如此,我认为通过计算产生NAN正是上述代码的问题所在。只有当两个不同的质量占据一个位置时。我不是一个孩子