Java/Processing 计算返回 "NaN" 和 "Infinity"
Java/Processing calculations returning "NaN" and "Infinity"
我正在尝试在 Processing/Java 中模拟 three-body problem。我创建了一个 Planet 对象并定义了几个函数来计算行星的吸引力、力和速度。程序运行没有任何错误。问题在于计算返回 Infinity 和
NaN 输出。
我还没有发现任何被零除的错误。
为什么要这样做?
float simulationTime = 0.01;
float earthMass = pow(10,24)*5.972;
Planet[] bodies = {new Planet(100,200, 0, 0,earthMass/2),
new Planet(400,500, 0, 0,earthMass/2),
new Planet(800,200, 0, 0,earthMass/2)};
int size = 500;
float G = 6.674*pow(10, -11);
float gravAttract(float mass1, float mass2, float x1, float y1, float x2, float y2) {
float force = G*mass1*mass2/pow(dist1(x1, y1, x2, y2), 2);
//println(pow(dist1(x1, y1, x2, y2), 2));
//println(force);
return force;
}
float attract(Planet one,Planet two){
float force = G*one.mass*two.mass/pow(dist1(one.xpos,one.ypos,two.xpos,two.ypos),2);
println(one.xpos,two.xpos,one.xspeed,two.xspeed);
return force;
}
float[] forceXY(int body){
float[] xy = {0,0};
for (int ii = 0; ii<bodies.length; ii = ii+1){
if (ii == body){
continue;
}
else{
xy[0] = xy[0]+attract(bodies[body],bodies[ii])*
(bodies[ii].xpos-bodies[body].xpos)/dist1(bodies[body].xpos,bodies[body].ypos,bodies[ii].xpos,bodies[ii].ypos);
xy[1] = xy[1]+attract(bodies[body],bodies[ii])*
(bodies[ii].ypos-bodies[body].ypos)/dist1(bodies[body].xpos,bodies[body].ypos,bodies[ii].xpos,bodies[ii].ypos);
println(xy);
}
}
return xy;
}
float dist1(float x1,float y1,float x2,float y2){
float x = dist(x1,y1,x2,y2);
x = x*149.6*pow(10,7);
//println(x1,y1,x2,y2);
return x;
}
class Planet {
float xpos;
float ypos;
float xspeed;
float yspeed;
float mass;
Planet(float a, float b, float c, float d, float e) {
xpos = a;
ypos = b;
xspeed = c;
yspeed = d;
mass = e;
}
void update(float xforce, float yforce) {
//println("xy",xpos,ypos);
float xa = xforce/mass;
float ya = yforce/mass;
xspeed = xspeed + xa*simulationTime;
yspeed = yspeed + ya*simulationTime;
xpos = xpos + xspeed*simulationTime;
ypos = ypos + yspeed*simulationTime;
}
}
void setup() {
size(1000, 1000);
frameRate(1);
}
void draw() {
background(0);
for (int ii = 0; ii < bodies.length; ii = ii+1){
float[] asdf = new float[2];
asdf = forceXY(ii);
circle(bodies[ii].xpos,bodies[ii].ypos,10);
bodies[ii].update(asdf[0],asdf[1]);
}
}
我看到您正在尝试使用实际物理值进行计算。问题在于天文质量、距离和力都是天文数字,不仅是字面上的,而且是比喻上的。数字太大,无法使用float
数据类型的有限范围表示中间计算的结果。
解决方法是更改单位。例如,不使用米、千克和秒,而是以“天文单位”(地球和太阳之间的距离)测量距离,以地球质量的倍数测量质量,以年为单位测量时间。或者使用标准 "astronomical system of units"。最重要的是,这会改变引力常数 G 的值。
如果您不太热衷于进行模拟来预测行星的真实位置,那么只需“即兴发挥”并设置 G=1、将质量设置为较小的数字,以及玩弄速度。你会发现想出一个逼真的模拟是非常容易的。
我正在尝试在 Processing/Java 中模拟 three-body problem。我创建了一个 Planet 对象并定义了几个函数来计算行星的吸引力、力和速度。程序运行没有任何错误。问题在于计算返回 Infinity 和 NaN 输出。 我还没有发现任何被零除的错误。 为什么要这样做?
float simulationTime = 0.01;
float earthMass = pow(10,24)*5.972;
Planet[] bodies = {new Planet(100,200, 0, 0,earthMass/2),
new Planet(400,500, 0, 0,earthMass/2),
new Planet(800,200, 0, 0,earthMass/2)};
int size = 500;
float G = 6.674*pow(10, -11);
float gravAttract(float mass1, float mass2, float x1, float y1, float x2, float y2) {
float force = G*mass1*mass2/pow(dist1(x1, y1, x2, y2), 2);
//println(pow(dist1(x1, y1, x2, y2), 2));
//println(force);
return force;
}
float attract(Planet one,Planet two){
float force = G*one.mass*two.mass/pow(dist1(one.xpos,one.ypos,two.xpos,two.ypos),2);
println(one.xpos,two.xpos,one.xspeed,two.xspeed);
return force;
}
float[] forceXY(int body){
float[] xy = {0,0};
for (int ii = 0; ii<bodies.length; ii = ii+1){
if (ii == body){
continue;
}
else{
xy[0] = xy[0]+attract(bodies[body],bodies[ii])*
(bodies[ii].xpos-bodies[body].xpos)/dist1(bodies[body].xpos,bodies[body].ypos,bodies[ii].xpos,bodies[ii].ypos);
xy[1] = xy[1]+attract(bodies[body],bodies[ii])*
(bodies[ii].ypos-bodies[body].ypos)/dist1(bodies[body].xpos,bodies[body].ypos,bodies[ii].xpos,bodies[ii].ypos);
println(xy);
}
}
return xy;
}
float dist1(float x1,float y1,float x2,float y2){
float x = dist(x1,y1,x2,y2);
x = x*149.6*pow(10,7);
//println(x1,y1,x2,y2);
return x;
}
class Planet {
float xpos;
float ypos;
float xspeed;
float yspeed;
float mass;
Planet(float a, float b, float c, float d, float e) {
xpos = a;
ypos = b;
xspeed = c;
yspeed = d;
mass = e;
}
void update(float xforce, float yforce) {
//println("xy",xpos,ypos);
float xa = xforce/mass;
float ya = yforce/mass;
xspeed = xspeed + xa*simulationTime;
yspeed = yspeed + ya*simulationTime;
xpos = xpos + xspeed*simulationTime;
ypos = ypos + yspeed*simulationTime;
}
}
void setup() {
size(1000, 1000);
frameRate(1);
}
void draw() {
background(0);
for (int ii = 0; ii < bodies.length; ii = ii+1){
float[] asdf = new float[2];
asdf = forceXY(ii);
circle(bodies[ii].xpos,bodies[ii].ypos,10);
bodies[ii].update(asdf[0],asdf[1]);
}
}
我看到您正在尝试使用实际物理值进行计算。问题在于天文质量、距离和力都是天文数字,不仅是字面上的,而且是比喻上的。数字太大,无法使用float
数据类型的有限范围表示中间计算的结果。
解决方法是更改单位。例如,不使用米、千克和秒,而是以“天文单位”(地球和太阳之间的距离)测量距离,以地球质量的倍数测量质量,以年为单位测量时间。或者使用标准 "astronomical system of units"。最重要的是,这会改变引力常数 G 的值。
如果您不太热衷于进行模拟来预测行星的真实位置,那么只需“即兴发挥”并设置 G=1、将质量设置为较小的数字,以及玩弄速度。你会发现想出一个逼真的模拟是非常容易的。