加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

重力计算导致NaN.没有明确的理由

发布时间:2020-12-16 10:08:32 所属栏目:百科 来源:网络整理
导读:我的C代码有问题. 它是2D中N体问题的强制解决方案. 有时我将NaN作为struct instance params值. 我的猜测是分裂出了问题.我已经分析了很多案例,但仍然找不到导致值为NaN的出现模式. 这是我的代码: #include stdio.h#include math.h#include time.h#include s
我的C代码有问题.
它是2D中N体问题的强制解决方案.
有时我将NaN作为struct instance params值.

我的猜测是分裂出了问题.我已经分析了很多案例,但仍然找不到导致值为NaN的出现模式.

这是我的代码:

#include <stdio.h>
#include <math.h>
#include <time.h>
#include <stdlib.h>

double G;  
int N;
int T;
int COUNT;

typedef struct 
{
    double rx,ry;
    double vx,vy;
    double fx,fy;
    double mass;
} Body;

void updateBody (Body* bodyInstance,int timestamp) {
    bodyInstance->vx += timestamp * bodyInstance->fx / bodyInstance->mass;
    bodyInstance->vy += timestamp * bodyInstance->fy / bodyInstance->mass;
    bodyInstance->rx += timestamp * bodyInstance->vx;
    bodyInstance->ry += timestamp * bodyInstance->vy;
};

void updateBodyForces (Body* bodyA,Body* bodyB) {
    double dx,dy,dist,force;
    dx = bodyB->rx - bodyA->rx;
    dy = bodyB->rx - bodyA->rx;
    // collision/same place in spacetime hack
    if (bodyB->rx == bodyA->rx && bodyB->ry == bodyA->ry) {
        dist = 1;
    } else {
        dist = sqrt(pow(dx,2) + pow(dy,2));
    }
    force = (G * bodyA->mass * bodyB->mass) / (pow(dist,2) + 100);
    bodyA->fx += force * dx / dist;
    bodyA->fy += force * dy / dist;
}

void resetBodyForces (Body* bodyInstance) {
    bodyInstance->fx = 0;
    bodyInstance->fy = 0;
}

void getRandomBody (Body* bI) {
    bI->rx = rand() % 10;
    bI->ry = rand() % 10;
    bI->vx = rand() % 10;
    bI->vy = rand() % 10;
    bI->fx = 0;
    bI->fy = 0;
    bI->mass = 20;
}

int main( int argc,char *argv[] )  {
    G = argc >= 2 ? atof(argv[1]) : 0.01;  
    N = argc >= 3 ? atoi(argv[2]) : 3;
    T = argc >= 4 ? atoi(argv[3]) : 1;
    COUNT = argc >= 5 ? atoi(argv[4]) : 10;
    srand(time(NULL));
    Body bodies[N];
    for (int i=0; i<N; i++) {
        getRandomBody(&bodies[i]);
    }
    for (int i = 0; i < COUNT; i++) {
        for (int j = 0; j < N; j++) {
            resetBodyForces(&bodies[j]);
            for (int k = 0; k < N; k++) {
                if (j != k) {
                    updateBodyForces(&bodies[j],&bodies[k]);
                }
            }
        }
        for (int j = 0; j < N; j++) {
            updateBody(&bodies[j],T);
        }
    }
}

解决方法

由于(i)pow的基本参数为负数,或(ii)您的笑话数字累积,因此-NaN结果的常见(并且到目前为止最可能的解释)生成-NaN结果是sqrt的负参数.浮点变量:bodyInstance-> vx =& c.将累积舍入误差.

在调用sqrt之前检查该情况.

您还将得到一个表达式为0.0 / 0.0的NaN,但我从未见过平台在该实例中产生负NaN.

所以这里的道德是偏爱dx * dx到pow(dx,2):前者更准确,不容易受到负dx的意外结果的影响,当然也不会慢.更好的是,使用C标准库中的hypot.

参考:http://en.cppreference.com/w/c/numeric/math/hypot

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读