/ Vijos / 讨论 / 分享 /

模拟匀速圆周运动

正好在复习物理,看到了必修二的P21的探究向心加速度大小的表达式。
想用计算机模拟一下一个质点在做匀速圆周运动时候的各个时刻的坐标。
怎么做呢?一个问题就是运动是连续的,从t1~t2,v在变并且a也在变,为了解决这个问题,可以近似处理,从t1~t2,我们只计算出a的变化但不将a的变化作用到v上,所以这个时间内就是匀速直线运动,下一个段时间t2~t3开始时,再把a的变化结算一下,改变v,接下来重复这个过程。
然后当间隔取的很小的时候就非常近似了。(感受一下微积分思想)

#include <bits/stdc++.h>
using namespace std;
#define FOR(i,n) for (int i=1;i<=n;i++)
#define REP(i,a,b) for (int i=a;i<=b;i++)

double x,y,r,v,t;
double vx,vy;
double x2,y2;
int a;
void change(double &x,double &y) {
    double a=v*v/r;
    double dvx,dvy;
    if (x<=0&&y>=0) {
        dvx=a*t*fabs(x)/r;
        dvy=a*t*fabs(y)/r;
        vx+=dvx,vy-=dvy;
    } else if (x>=0&&y>=0) {
        dvx=a*t*fabs(x)/r;
        dvy=a*t*fabs(y)/r;
        vx-=dvx,vy-=dvy;
    } else if (x<=0&&y<=0) {
        dvx=a*t*fabs(x)/r;
        dvy=a*t*fabs(y)/r;
        vx+=dvx,vy+=dvy;
    } else {
        dvx=a*t*fabs(x)/r;
        dvy=a*t*fabs(y)/r;
        vx-=dvx,vy+=dvy;
    }
}
int main() {
    //freopen("out.txt","w",stdout);
    cin>>r>>v;
    x=0,y=1;
    t=1e-4;
    int cnt=100000;
    vx=-1,vy=0;
    while (cnt--) {
        x2=x+vx*t,y2=y+vy*t;
        change(x,y);
        x=x2,y=y2;
        if (cnt%100==0) {
            printf("%.9lf %.9lf\n",x,y);
            //printf("%.9lf\n",sqrt(x*x+y*y));
        }
    }
    return 0;
}

将文件输出的注释删掉,把out.txt里的数据复制到excel里可以用图表显示.
https://pan.baidu.com/s/1SqTshEskxFx54pwRV66zlg

1 条评论

  • @ 2019-06-28 14:57:39

    今天回顾的时候突然发现我的算法难道不会每次都向圆周外偏离一点点距离的吗?
    因为我在走的时候是直接沿着v的方向走一段距离,因为v是和圆相切的,所以会走出圆周一段距离。但是我想了一下还是没问题的,假设我们每过dθ就计算一次,那么我们位置的径向偏差只会累加r(dθ)^2,注意是平方哦,如果是rdθ的话,那么当dθ累加到θ的时候,偏差也会累加到rθ,但是这里是(dθ)^2,即使所有dθ的和是固定的,只要我们把每次的dθ取得足够小,仍然可以让它们的平方和小于任一给定正数,因此它是趋于无穷小的。所以这个算法是可行的。

    • @ 2019-06-30 22:20:29

      很厉害。
      (dθ)^2是高阶无穷小,可以忽略。

  • 1