我正在编写一个程序,计算物体以给定速度直线向上投掷时的行进距离。
现在我需要实现角度,看看与直接向上投掷时相比,这会如何影响每秒的高度损失。
我被告知要使用数学图书馆,但我不知道从这里到哪里去。
//The following calculation can be used to calculate the correlation between time and height
//h(t )=−0.5⋅G⋅t^2+V⋅T+H
#include <iostream>
#include <limits>
using namespace std;
int main() {
//Falling speed
const double G = 9.81;
//Starting height
double H = 0;
//Velocity/Speed
double V = 0;
//End product
double Ht = 0;
//Seconds that result is displayed on the screen
double T = 0;
//t^2
double Tt = 0;
int S;
int s = 1;
cout << "nGive me the starting height: ";
while(!(cin >> H)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), 'n');
cout << "False input. Try again: ";
}
cout << "nGive me the starting speed: ";
while(!(cin >> V)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), 'n');
cout << "False input. Try again: ";
}
cout << "nHow often do you want the current height to be displayed (In seconds)n";
while(!(cin >> S)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), 'n');
cout << "False input. Try again: ";
}
for (int i = 0; i < 10; i = i + S) {
Tt = i*i;
Ht = -0.5 * G * Tt + V * i + H;
if (Ht >= 0){
cout << "Second " << s << " the height is " << Ht << " Meters" << endl;
s += 1;
} else {
Ht = 0;
cout << "Second " << s << " the height is " << Ht << " Meters" << endl;
i = 9;
}
}
}
感谢您的帮助。
您正朝着正确的方向起步,但在尝试实现"特殊情况";保持你的算术符号正确。不要那样做。在运动学和动力学中,每个位置、速度或加速度都相对于您选择的坐标系。如果你的矢量方向是一致的,你就再也不用担心特殊情况了。
嗯?你是什么意思
以你的重力项const double G = 9.81;
为例。除非您将Y坐标定义为向下的正坐标,否则G
上的符号是错误的(陷阱…)。大多数正常的笛卡尔坐标系都将Y定义为向上的正坐标(屏幕坐标和机身坐标除外)。当Y轴向上为正时,重力的作用方向是什么?(如果感到困惑,"扔石头"——我的一位老教授:)
的建议
重力以向下的方向作用,因此应声明为负值,Y向上为正值。因为随着代码的增长,几乎所有的计算函数都需要这个术语,所以你也可以将其全局化:
static const double G = -9.81; /* global constant is fine, pay attention to sign */
然后,对于基于加速度和时间进行的每个位置计算,只需使用标准公式:
X = Xo + Vo * t + 0.5 * a * t * t;
无需在计算中插入伪'-'
符号,也无需为输出划分特殊情况。当你增加作用在你的投射物上的力时,保持你的力的方向是至关重要的。所有的力都是矢量,都有一个方向。如果你总是把正确的方向赋予每一个力,你就不必再调整公式或担心特殊情况了。
对于您的计算,这意味着您可以简单地使用:
for (int i = 0; i < 15; i = i + S) {
double Tt = i * i, /* seconds squared */
Ht = H + V * i + 0.5 * G * Tt, /* pos based on acceleration & time */
Vt = V + G * i; /* vel based on acceleration & time */
...
(注意:基本迭代次数增加到15
,这是充分观察以100 m/s或更低速度向上发射的物体的高度反转所需的——任何更快的速度和大气可压缩性都会成为一个因素)
考虑输入的连续循环
当您想要求用户提供有效的输入时,使用连续循环并在满足条件时中断读取循环会更方便。(这允许您在循环中完全包含提示和错误报告)。例如,你可以做:
while (true) { /* loop continually until valid input (prompt within) */
std::cout << "nStarting height : ";
if (std::cin >> H)
break;
std::cin.clear();
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), 'n');
std::cerr << "False input. Try again: "; /* error output on cerr */
}
(注意:正确使用std::cin.ignore()
做得好,您可能还想区分稍后设置的eofbit
和failbit
,但您做得很好)
在最终输入之后,您可以添加一个std::cout.put ('n');
来提供分隔输入值和输出值的换行符。
举个例子,保存std::cout
的格式化标志,然后将fixed
的输出精度设置为2
,你可以这样做:
#include <iostream>
#include <iomanip>
#include <limits>
static const double G = -9.81; /* global constant is fine, pay attention to sign */
int main () {
double H = 0; /* starting height */
double V = 0; /* initial velocity */
int S; /* time step (seconds) */
while (true) { /* loop continually until valid input (prompt within) */
std::cout << "nStarting height : ";
if (std::cin >> H)
break;
std::cin.clear();
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), 'n');
std::cerr << "False input. Try again: "; /* error output on cerr */
}
while (true) {
std::cout << "Starting speed : ";
if (std::cin >> V)
break;
std::cin.clear();
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), 'n');
std::cerr << "False input. Try again: ";
}
while (true) {
std::cout << "Time Step (In seconds) : ";
if (std::cin >> S) {
std::cout.put ('n'); /* tidy up with additional newline */
break;
}
std::cin.clear();
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), 'n');
std::cerr << "False input. Try again: ";
}
std::ios_base::fmtflags f = std::cout.flags(); /* save format flags */
std::cout << std::fixed; /* set fixed precision */
std::cout.precision(2); /* of 2 */
for (int i = 0; i < 15; i = i + S) {
double Tt = i * i, /* seconds squared */
Ht = H + V * i + 0.5 * G * Tt, /* pos based on acceleration & time */
Vt = V + G * i; /* vel based on acceleration & time */
std::cout << "Second: " << std::setw(3) << i
<< " Height: " << std::setw(6) << Ht
<< " Velocity: " << std::setw(6) << Vt << 'n';
}
std::cout.flags(f); /* restore default precision */
}
(注意:在计算或输出格式中没有"特殊情况"。还可以考虑将S
设置为double
类型,以便您可以输入,例如.2
或.1
作为时间步长,以便在输出中获得更精细的粒度。您还可以添加StartTime
和StopTime
的输入,这将允许在短(或长)时间内对输出进行非常精细的检查周期)
示例使用/输出
例如,如果你以一枚初始高度为10
米、初始向上速度为100 m/s
的炮弹为例,你可以观察到速度在哪里降到零,然后随着它落回地球而开始增加。你会看到同样的高度反转。
$ ./bin/kinematic_h+v
Starting height : 10
Starting speed : 100
Time Step (In seconds) : 1
Second: 0 Height: 10.00 Velocity: 100.00
Second: 1 Height: 105.09 Velocity: 90.19
Second: 2 Height: 190.38 Velocity: 80.38
Second: 3 Height: 265.86 Velocity: 70.57
Second: 4 Height: 331.52 Velocity: 60.76
Second: 5 Height: 387.38 Velocity: 50.95
Second: 6 Height: 433.42 Velocity: 41.14
Second: 7 Height: 469.65 Velocity: 31.33
Second: 8 Height: 496.08 Velocity: 21.52
Second: 9 Height: 512.69 Velocity: 11.71
Second: 10 Height: 519.50 Velocity: 1.90
Second: 11 Height: 516.50 Velocity: -7.91
Second: 12 Height: 503.68 Velocity: -17.72
Second: 13 Height: 481.05 Velocity: -27.53
Second: 14 Height: 448.62 Velocity: -37.34
如果你想要两个时间步长,你可以这样做:
$ ./bin/kinematic_h+v
Starting height : 10
Starting speed : 100
Time Step (In seconds) : 2
Second: 0 Height: 10.00 Velocity: 100.00
Second: 2 Height: 190.38 Velocity: 80.38
Second: 4 Height: 331.52 Velocity: 60.76
Second: 6 Height: 433.42 Velocity: 41.14
Second: 8 Height: 496.08 Velocity: 21.52
Second: 10 Height: 519.50 Velocity: 1.90
Second: 12 Height: 503.68 Velocity: -17.72
Second: 14 Height: 448.62 Velocity: -37.34
(注意:要求解炮弹达到最大高度的确切时间,只需在正常的V = Vo + a * t
方程中将最终速度设置为0
,然后求解t
,例如t = -Vo / a
。这里有一个很好的运动学计算器-Physics Catalyst,它还提供了供您使用的螺母和螺栓运动方程。)
最后,看看为什么"使用命名空间std;"被认为是不好的做法?。早养成好习惯要比晚改掉坏习惯容易得多。。。
移动到三维空间
在处理三维问题的方式上几乎没有区别。代替使用H
和V
,使用保持double x, y, z;
坐标和速度的struct
变得更容易。然后,您的函数只需使用完全相同的公式独立地对x
、y
和z
成员进行操作。然后,对于最终值,仅为平方和的平方根和所得角度的atan2()
。
此外,在三维中工作时,可以使用矢量点积和叉积,当您开始使用角速率和度量时,这些积会变得越来越有用。
仔细看看,如果你还有问题,请告诉我。