回答編集履歴
9
rangesは結局使わなかったので削除。
answer
CHANGED
@@ -20,7 +20,6 @@
|
|
20
20
|
#include <numeric> // accumulate
|
21
21
|
#include <algorithm> // reverse
|
22
22
|
#include <utility> // pair
|
23
|
-
#include <ranges> // C++20以上で必要(オプション)
|
24
23
|
|
25
24
|
using Vec2 = std::pair<double, double>;
|
26
25
|
using Record = std::tuple<double, Vec2, Vec2>; // (t, r, v)
|
8
コードの計算過程の出力を、原作の意図通り、0.1秒毎出力へと変更
answer
CHANGED
@@ -77,8 +77,10 @@
|
|
77
77
|
std::cout << std::fixed << std::setprecision(10);
|
78
78
|
std::reverse(data.begin(), data.end());
|
79
79
|
for (const auto& [t, r, v] : data) {
|
80
|
+
if (std::fmod(t / 0.01, 10) < 1e-9) { // t が 0.1, 0.2, 0.3 ... のときだけ出力
|
80
|
-
|
81
|
+
std::cout << t << ", " << r.first << ", " << r.second
|
81
|
-
|
82
|
+
<< ", " << v.first << ", " << v.second << '\n';
|
83
|
+
}
|
82
84
|
}
|
83
85
|
|
84
86
|
const auto& [tf, rf, vf] = data.back();
|
7
注釈を修正
answer
CHANGED
@@ -235,5 +235,5 @@
|
|
235
235
|
|
236
236
|
注1: [```std::setprecition```](https://cpprefjp.github.io/reference/iomanip/setprecision.html)ではそこに書かれてる通り、「浮動小数点数を出力する精度を設定」してて、[```std::fixed```](https://cpprefjp.github.io/reference/ios/fixed.html)では、「浮動小数点数を固定小数点表記で入出力することを指示」しているだけだ。
|
237
237
|
|
238
|
-
注2: なお、オリジナルのコードでもx
|
238
|
+
注2: なお、オリジナルのコードでも速度vのx成分の初期値に```cos(1/2 * Π)```が使われてるんで、全履歴は水平方向だと位置情報は0のまんま、速度のx成分も0のまんま、となると思う。
|
239
|
-
結果、
|
239
|
+
結果、事実上このシミュレーションは鉛直方向への「投げ上げ」って事になるんじゃなかろうか。
|
6
マークダウン修正
answer
CHANGED
@@ -125,7 +125,7 @@
|
|
125
125
|
繰り返すけど、多々の情報を**纏めて扱う**ってのはモダンなプログラミングでは重要な概念で、STLを備えたC++はその「モダンなプログラミング」に片足突っ込んでいて、その辺実は古典的なCとは全く違う思想を持っている。
|
126
126
|
この後それを知ることとなる。
|
127
127
|
|
128
|
-
次はユーティリティ
|
128
|
+
次はユーティリティ```arange```だ。
|
129
129
|
|
130
130
|
```C++
|
131
131
|
std::vector<double> arange(double start, double end, double step) {
|
5
本文修正
answer
CHANGED
@@ -107,7 +107,7 @@
|
|
107
107
|
```
|
108
108
|
|
109
109
|
として二次元ベクトル、```Vec2```型、ってのを定義している。
|
110
|
-
厳密に言うと、```Vec2```型を[```std::pair```](https://cpprefjp.github.io/reference/utility/pair.html)への[エイリアス](https://e-words.jp/w/%E3%82%A8%E3%82%A4%E3%83%AA%E3%82%A2%E3%82%B9.html)として用いる、と言う事だ。
|
110
|
+
厳密に言うと、```Vec2```型を[```std::pair<double, double>```](https://cpprefjp.github.io/reference/utility/pair.html)への[エイリアス](https://e-words.jp/w/%E3%82%A8%E3%82%A4%E3%83%AA%E3%82%A2%E3%82%B9.html)として用いる、と言う事だ。
|
111
111
|
これにより```r = (x, y)```とか```v = (vx, vy)```みたいな、**より物理学らしい**表現が可能となる。
|
112
112
|
|
113
113
|
もう一つは```Record```型の定義だ。
|
4
時間列の範囲指定ミスを修正
answer
CHANGED
@@ -65,7 +65,7 @@
|
|
65
65
|
};
|
66
66
|
|
67
67
|
std::vector<Record> initial = { std::make_tuple(t_0, r_0, v_0) };
|
68
|
-
std::vector<double> steps = arange(t_0 + h, t_n
|
68
|
+
std::vector<double> steps = arange(t_0 + h, t_n, h);
|
69
69
|
|
70
70
|
std::vector<Record> data = std::accumulate(
|
71
71
|
steps.begin(), steps.end(), initial,
|
3
係数を2Mで割るのを忘れてた・・・・・・orz
answer
CHANGED
@@ -43,7 +43,7 @@
|
|
43
43
|
|
44
44
|
std::vector<Record> foo(const std::vector<Record>& acc, double s) {
|
45
45
|
const auto& [t, r, v] = acc.front(); // 先頭が最新状態
|
46
|
-
double coeff = - rho * Cd * S * std::sqrt(v.first * v.first + v.second * v.second);
|
46
|
+
double coeff = - rho * Cd * S * std::sqrt(v.first * v.first + v.second * v.second) / (2 * M);
|
47
47
|
Vec2 r_new = {
|
48
48
|
r.first + h * v.first,
|
49
49
|
r.second + h * v.second
|
2
計算結果上の注釈を付けた。
answer
CHANGED
@@ -233,4 +233,7 @@
|
|
233
233
|
あとは出力するだけ、となる。
|
234
234
|
おしまい。
|
235
235
|
|
236
|
-
|
236
|
+
注1: [```std::setprecition```](https://cpprefjp.github.io/reference/iomanip/setprecision.html)ではそこに書かれてる通り、「浮動小数点数を出力する精度を設定」してて、[```std::fixed```](https://cpprefjp.github.io/reference/ios/fixed.html)では、「浮動小数点数を固定小数点表記で入出力することを指示」しているだけだ。
|
237
|
+
|
238
|
+
注2: なお、オリジナルのコードでもx座標の初期値に```cos(1/2 * Π)```が使われてるんで、実は水平方向だと位置情報は0のまんま、となると思う。
|
239
|
+
結果、時間経過があってもxは全て0のまま、速度vのx成分も0のまま、となって、事実上このシミュレーションは鉛直方向への「投げ上げ」って事になるんじゃなかろうか。
|
1
マークダウンを修正
answer
CHANGED
@@ -227,7 +227,7 @@
|
|
227
227
|
|
228
228
|
```
|
229
229
|
|
230
|
-
時間列が```end```に到達するまで、```std::accumulate```は関数```foo``を利用しつつ```initial```を加工していく。最終的には時間列の長さ(この問題の場合は200)に合わせて古い順から並んだ200個の計算結果(```(t, r, v)```)が詰め込まれたシーケンスを入手する。
|
230
|
+
時間列が```end```に到達するまで、```std::accumulate```は関数```foo```を利用しつつ```initial```を加工していく。最終的には時間列の長さ(この問題の場合は200)に合わせて古い順から並んだ200個の計算結果(```(t, r, v)```)が詰め込まれたシーケンスを入手する。
|
231
231
|
これでオイラー法は終了、だ。
|
232
232
|
|
233
233
|
あとは出力するだけ、となる。
|