前言
在物理学的基本定律中,能量是守恒的,即它不会无中生有,也不会完全消失,而是会在不同形式之间转换。如果在绝对理想的状态下,我们能不能撞击出来圆周率呢?
启发
其中,mA 和 mB 分别是物体A和B的质量,vA 和 vB 是碰撞前物体A和B的速度,vA1 和 vB1 是碰撞后物体A和B的速度。
对于完全弹性碰撞,除了动量守恒外,还有动能守恒:
将动量守恒的公式解出vA1,并结合动能守恒的公式,可以推导出碰撞后物体A的速度vA1的表达式,即你给出的公式:
这个公式适用于一维碰撞(即碰撞前后物体都在同一直线上运动)且为完全弹性碰撞的情况。在完全弹性碰撞中,碰撞前后的总动能保持不变,这是与非弹性碰撞(如塑性碰撞)的主要区别。在非弹性碰撞中,部分动能会转化为内能或其他形式的能量,导致总动能减少。
通过以上公式,我们可以模拟出来A球和B球碰撞后的速度,然后我们将这个速度记录下来。
void updateCollision(double& v_A, double& v_B)
{
double v_A_1 = ((m_A - m_B) * v_A + 2 * m_B * v_B) / (m_A + m_B);
double v_B_1 = ((m_B - m_A) * v_B + 2 * m_A * v_A) / (m_A + m_B);
v_A = v_A_1;
v_B = v_B_1;
}
有了速度,我们就可以绘制出来每次小球的位置和撞击的效果。当两个小球的质量相同,碰撞后会发生什么呢?模拟情况如下:
我们可以看到撞击了3次,撞击后相当于速度交换。这个3就是圆周率的首位。当红球的质量是白球的100倍时,碰撞会发生什么呢?模拟情况如下:
我们可以看到撞击了31次,这个31就是圆周率的前两位。
源码
///////////////////////////////////////////////////
// 程序名称:碰撞出来的圆周率
// 编译环境:Mictosoft Visual Studio 2022, EasyX_20200315(beta)
// 作 者:luoyh <2864292458@qq.com>
// 最后修改:2024-5-22
// 公 众 号:C语言研究
//
using namespace std;
double const m_A = 100; // 红球质量
double const m_B = 1; // 白球质量
double v_A = 0.01; // 红球速度
double v_B = 0.0; // 白球速度
int const LO = 640;
int const WIDY = 480;
void updateCollision(double& v_A, double& v_B)
{
double v_A_1 = ((m_A - m_B) * v_A + 2 * m_B * v_B) / (m_A + m_B);
double v_B_1 = ((m_B - m_A) * v_B + 2 * m_A * v_A) / (m_A + m_B);
v_A = v_A_1;
v_B = v_B_1;
}
void DrawBall(int x, int y, int r, COLORREF color)
{
setfillcolor(color);
setlinestyle(PS_SOLID,2);
fillcircle(x, y, r);//A球
}
int main()
{
vector<double> Va, Vb;
Va.push_back(v_A); // 初始速度
Vb.push_back(v_B);
int a = 0;
while (true)
{
updateCollision(v_A, v_B);
a++;
Va.push_back(v_A);
Vb.push_back(v_B);
// 检查碰撞结束条件
if (fabs(v_B) < fabs(v_A) && v_B <= 0 && v_A < 0)
{
break;
}
v_B = -v_B; // 碰墙后速度反向
a++;
Va.push_back(v_A);
Vb.push_back(v_B);
// 检查碰墙后的结束条件
if (fabs(v_B) < fabs(Va[0]))
{ // 使用初始的v_A进行比较
break;
}
}
initgraph(LO + 500, WIDY);
double X, Y;
X = LO / 8;
Y = WIDY * 4 / 5;
setlinecolor(YELLOW);
setlinestyle(PS_SOLID,4);
line(X, Y / 4, X, Y);//从上往下画的直线
line(X, Y, X * 13, Y);//从左往右画的直线
DrawBall(X * 7, Y - Y / 16, Y / 16, RED);
DrawBall(X * 5, Y - Y / 16, Y / 16, WHITE);
//当两球心距离为Y/8时,则定义两球碰撞成功
//当球的坐标为(X+Y/8,Y-Y/16)时,定义碰墙成功
a = 0;
int t = 50;
double A, B;
A = X * 7;
B = X * 5;
_getch();
BeginBatchDraw();
while (1)
{
setlinecolor(YELLOW);
line(X, Y / 4, X, Y);//从上往下画的直线
line(X, Y, X * 13, Y);//从左往右画的直线
A -= Va[a] * t;
B -= Vb[a] * t;
DrawBall(A, Y - Y / 16, Y / 16, RED);
DrawBall(B, Y - Y / 16, Y / 16, WHITE);
if (A - B <= Y / 8 || B <= X + Y / 16)
{
a++;
}
settextstyle(40,0,_T("楷体"));
settextcolor(WHITE);
RECT r = { 0, 0, LO + 500, 100 };
drawtext(_T("圆周率碰撞实验"), &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
settextstyle(25, 0, _T("楷体"));
char H_A[126];
char H_B[126];
sprintf_s(H_A, "红球质量:%.0lf ,当前速度:%.10lf", m_A,Va[a]);
sprintf_s(H_B, "白球质量:%.0lf ,当前速度:%.10lf", m_B, Vb[a]);
outtextxy(280, 100, H_A);
outtextxy(280, 130, H_B);
char s[126];
sprintf_s(s, "碰撞次数:%d (包括球撞击墙和球撞击球)", a);
outtextxy(280, 160, s);
FlushBatchDraw();
Sleep(1);
cleardevice();
}
EndBatchDraw();
_getch();
return 0;
}
红球是白球质量的10000000倍时,会发生什么?
碰撞的时间有点久,当然这个只是在理想状态撞击,如果现实中,质量差距这么大,直接就碰到墙里面了。