使用迭代公式为 C 数组赋值

Assigning value to C array with iterative formula

提问人:Aldehyde 提问时间:1/27/2021 更新时间:1/28/2021 访问量:49

问:

上下文

我想模拟粒子在电场中的轨迹。我想要它在每个时间步的位置、速度和加速度。这些变量中的每一个都将存储在一个数组中,因此我可以将其写入文件并在以后绘制它。我的问题是我无法修改数组的值,当我打印时,我只能在整个数组上重复初始值。

我的代码

int main(){
    ////// Some variable definitions for the physics //////
    const float m_Ca  = 40*1.66053886e-27;
    const float Q_Ca  = 1.60217646e-19; 
    const float U_dc  = 1000;
    const float z0_2  = 20*20; // mm
    const float w_z_2 = 2*Q_Ca*U_dc/m_Ca/z0_2;
    
    // time step
    const float dt = 5e-9;
    const float dt1 = 0.5*5e-9;
    // simulation number of steps
    const int i_free_fly = round(10/sqrtf(w_z_2)/dt);
    ///////////////////////////////////////////////////////
    
    // allocating position, velocity and acceleration arrays
    float* r_z = (float*)malloc(i_free_fly*sizeof(float));
    float* v_z = (float*)malloc(i_free_fly*sizeof(float));
    float* a_z = (float*)malloc(i_free_fly*sizeof(float));
    // initializing arrays
    r_z[0] = 1;
    v_z[0] = 0;
    a_z[0] = 0;
    
    // Velocity-Verlet algorithm
    // here I calculate the next steps position, velocity and acceleration
    // for the current time step i I need info from the previous time step i-1
    for (int i=1;i<i_free_fly;++i){
        // update position
        r_z[i] = r_z[i-1] + v_z[i-1]*dt + 0.5*a_z[i-1]*dt1*dt1;
        // update acceleration
        a_z[i] = m_Ca*w_z_2*r_z[i];
        // update velocity
        v_z[i] = v_z[i-1] + dt1 * (a_z[i-1] + a_z[i]);
    }

    return 0;
}

我的问题

打印r_z时,v_z和a_z我随时得到 1、0、0 和零。我这样做是为了打印数组。

for (int i=1;i<150;++i){    
    printf("%f\n",r_z[i]);
    printf("%f\n",v_z[i]);
    printf("%f\n",a_z[i]);
}

我是 C 的新手,指针对我来说仍然很奇怪。我不知道使用它们是否是正确的方法,但在互联网上查看,我认为这是实现我目标的最佳方式,但我可能错过了一些东西。

c verlet 集成

评论

1赞 KamilCuk 1/28/2021
1.60217646e-19逗号后有那么多数字,您可能希望使用 S 甚至 S。doublelong double
0赞 Zois Tasoulas 1/28/2021
我不认为您的代码中存在指针问题。尝试检查您在循环中为 、 、 分配的值。他们似乎是 和 。forr_za_zv_z100
0赞 Brian Sidebotham 1/28/2021
我认为你的数学也有问题。请参阅维基百科页面上的“开始迭代”部分:en.wikipedia.org/wiki/Verlet_integration
1赞 Aldehyde 1/28/2021
事实上,加速度的真正表达式是:。通过这个方程,我可以看到粒子在我的谐波势内振荡,这是预期的行为。a_z[i] = -w_z_2*r_z[i]

答:

0赞 Brian Sidebotham 1/28/2021 #1

当像这样在 C 中处理非常小的数字时,你不能信任 printf 的格式运算符。取而代之的是,使用 like 给你一个指数输出,然后不会四舍五入:%f%e

for (int i=1;i<150;++i){    
    printf("%e\n",r_z[i]);
    printf("%e\n",v_z[i]);
    printf("%e\n",a_z[i]);
}

在修改后的版本中,我们可以看到加速度是恒定的(首先)并且速度增加:

    for( int i = 0; i < 156; i++ ) {
        printf("r_z: %e a_z: %e v_z: %e\n", r_z[i], a_z[i], v_z[i]);
    }
$ ./a.out 
r_z: 1.000000e+00 a_z: 0.000000e+00 v_z: 0.000000e+00
r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 2.002721e-27
r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 6.008162e-27
r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 1.001360e-26
r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 1.401904e-26
r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 1.802449e-26
r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 2.202993e-26
r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 2.603537e-26
r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 3.004081e-26
r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 3.404625e-26
r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 3.805169e-26
r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 4.205713e-26
r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 4.606257e-26
r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 5.006802e-26
r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 5.407346e-26
r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 5.807890e-26
r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 6.208434e-26
r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 6.608978e-26
r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 7.009522e-26
r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 7.410066e-26

或者,您可以选择改用类型字段,以便根据值决定是否使用指数表示。%gprintf