我正在尝试使用C在opengl中建立太阳系的模拟。我似乎无法弄清楚如何编写用于计算另一个人施加在行星上的力的方向的代码。这就是我到目前为止:
void attraction(planet self, planet other, float *direction)
{
float d = vecDistance(self.p, other.p);
//calc the force of attraction
float f = G * ((self.mass * other.mass) / (pow(d, 2)));
//calc the direction of the force
float vectorDist[3];
vecSub(self.p, other.p, vectorDist);
direction[0] = f*vectorDist[0] / d;
direction[1] = f*vectorDist[1] / d;
direction[2] = f*vectorDist[2] / d;
}
float vecDistance( float *pV1, float *pV2 )
{
float fLen=0.0f;
if(pV1 && pV2)
{
float av[3];
vecSub(pV2, pV1, av);
fLen=vecLength(av);
}
return fLen;
}
void vecSub( float *pV0, float *pV1, float *pVRes )
{
if(pV0 && pV1 && pVRes)
{
pVRes[0]=pV0[0]-pV1[0];
pVRes[1]=pV0[1]-pV1[1];
pVRes[2]=pV0[2]-pV1[2];
}
}
答案 0 :(得分:6)
没有输入数据很难知道,但我猜你遇到了浮点溢出,因为你操作的值太大了。
例如,如果您的单位在SI单位系统中,那么:
venus.mass = 4.87e+24; // kg
earth.mass = 5.98e+24; // kg
,等式中的分子变为:
self.mass * other.mass == 2.91047e+49;
单精度floating-point numbers不能大于3.4e + 38,因此质量乘积被视为无穷大。
当然,高指数在某种程度上相互抵消,因为距离也很大(大约1e + 10)且引力常数很小,但如果上述乘积是一个中间结果,则所有相关结果都是错了。 (-1.0#IND
表示 indefinte ,对应NaN
,不是数字,是无效的浮点数。)
有几种方法可以解决这个问题:
使用可在浮点状态下安全平方的值。例如,如果使用地球质量对质量进行归一化,则得到的数字大约为1.0,这对于进行计算应该是安全的。同样,距离的良好单位可能是astronomical unit。
重新排列表达式,以免中间表达式溢出。例如,而不是(m1 * m2) / (d*d)
,请写(m1 / d) * (m2 / d)
。
使用double
代替浮点数。最大可表示double
是约。 1.8E + 308。请注意,此问题不会随duoble
而消失,只会让您有更多的动作空间。举个例子,你应该很好。