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