C语言模拟——碰撞出来的圆周率

教育   2024-08-22 23:51   宁夏  

前言

在物理学的基本定律中,能量是守恒的,即它不会无中生有,也不会完全消失,而是会在不同形式之间转换。如果在绝对理想的状态下,我们能不能撞击出来圆周率呢?

启发

之所以提出在理想状态下进行撞击的设想,是因为现实世界的物理过程充满了复杂性和不确定性,包括摩擦力、空气阻力、材料弹性等多种因素,这些因素会极大地干扰我们尝试通过物理手段直接‘撞击’出圆周率这一纯粹数学常数的努力。在理想状态下,我们可以忽略这些干扰因素,设想一个完美的、无损耗的撞击环境,从而专注于探索物理过程与数学常数之间可能存在的微妙联系。
尽管撞击本身属于物理范畴,而圆周率则是数学领域的核心概念,两者看似距离甚远,但实际上,数学与物理在深层次上往往相互交织、息息相关。历史上不乏通过物理现象或实验来揭示数学规律的例子,这启示我们,在理想化的理论框架内,或许能够找到一种创新的方法,将物理的撞击过程与数学的圆周率计算巧妙地结合起来,尽管这在实际操作中可能面临巨大挑战。
思路
我使用C语言模拟一个理想的状态,来完成这一个碰撞理论,看看能不能碰撞出来圆周率。首先要了解一个知识点,就是弹性碰撞。
在完全弹性碰撞中,动能和动量都是守恒的。具体来说,这个公式来源于动量守恒和动能守恒(或称为机械能守恒)的应用。首先,动量守恒的公式为:


其中,mA 和 mB 分别是物体A和B的质量,v和 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语言研究//
#include <iostream>#include <graphics.h>#include <conio.h>#include <vector>
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倍时,会发生什么?

碰撞的时间有点久,当然这个只是在理想状态撞击,如果现实中,质量差距这么大,直接就碰到墙里面了。

C语言研究
写给自己的笔记,时常写写,时常看看,仅此而已。