はじめに
方程式は数学の基本です。物理を計算したり、アルゴリズムを扱ったり、ただ練習したりする際に、コードで解く方法を知っておくと非常に便利です。ここでは、4つのケースを見ていきましょう:
- 線形方程式 (ax + b = 0)
- 二次方程式 (ax² + bx + c = 0)
- 2つの線形方程式の連立 (2つの未知数)
- 三次方程式 (ax³ + bx² + cx + d = 0)
それぞれについて、数学の論理から始め、次に C++ と Python のコードに飛び込みます。
1. 線形方程式 (ax + b = 0)
解き方 (数学):
- bを反対側に移動: ax = -b.
- a = 0 かつ b = 0 の場合 → 無限に多くの解が存在します。
- a = 0 かつ b ≠ 0 の場合 → 解なし。
- それ以外の場合、x = -b/a.
C++:
#include <iostream>
#include <cmath>
using namespace std;
int main() {
double a, b;
cin >> a >> b;
if (fabs(a) < 1e-9) {
if (fabs(b) < 1e-9) cout << "無限の解\n";
else cout << "解なし\n";
} else {
cout << "x = " << -b/a << endl;
}
return 0;
}
Python:
a, b = map(float, input("a, b を入力してください: ").split())
if abs(a) < 1e-9:
if abs(b) < 1e-9:
print("無限の解")
else:
print("解なし")
else:
print("x =", -b/a)
2. 二次方程式 (ax² + bx + c = 0)
解き方 (数学):
- 判別式を計算: Δ = b² − 4ac.
- Δ < 0 の場合: 実数解なし。
- Δ = 0 の場合: 重解 x = −b/(2a).
- Δ > 0 の場合: 二つの解 x₁, x₂ を二次方程式の公式を使って求めます。
- a = 0 の場合: 線形に簡略化。
C++:
#include <iostream>
#include <cmath>
using namespace std;
int main() {
double a, b, c;
cin >> a >> b >> c;
if (fabs(a) < 1e-9) {
cout << "x = " << -c/b << "\n";
} else {
double delta = b*b - 4*a*c;
if (delta < 0) cout << "実数解なし\n";
else if (fabs(delta) < 1e-9) cout << "重解 x = " << -b/(2*a) << "\n";
else {
cout << "x1 = " << (-b + sqrt(delta))/(2*a) << "\n";
cout << "x2 = " << (-b - sqrt(delta))/(2*a) << "\n";
}
}
}
Python:
import math
a, b, c = map(float, input("a, b, c を入力してください: ").split())
if abs(a) < 1e-9:
print("x =", -c/b)
else:
delta = b*b - 4*a*c
if delta < 0:
print("実数解なし")
elif abs(delta) < 1e-9:
print("重解 x =", -b/(2*a))
else:
x1 = (-b + math.sqrt(delta))/(2*a)
x2 = (-b - math.sqrt(delta))/(2*a)
print("x1 =", x1, "x2 =", x2)
3. 2つの線形方程式の連立
形式:
ax + by = c
dx + ey = f
解き方 (数学):
- クレーマーの法則を使用します。
- 行列式: D = ae - bd.
- D ≠ 0 の場合: x = (ce - bf) / D
y = (af - cd) / D
- x = (ce - bf) / D
- y = (af - cd) / D
- D = 0 の場合: Dx = 0 かつ Dy = 0 の場合 → 無限に多くの解が存在します。
それ以外の場合 → 解なし。
- Dx = 0 かつ Dy = 0 の場合 → 無限に多くの解が存在します。
- それ以外の場合 → 解なし。
C++:
#include <iostream>
#include <cmath>
using namespace std;
int main() {
double a,b,c,d,e,f;
cin >> a >> b >> c >> d >> e >> f;
double D = a*e - b*d;
double Dx = c*e - b*f;
double Dy = a*f - c*d;
if (fabs(D) < 1e-9) {
if (fabs(Dx) < 1e-9 && fabs(Dy) < 1e-9) cout << "無限の解\n";
else cout << "解なし\n";
} else {
cout << "x = " << Dx/D << ", y = " << Dy/D << "\n";
}
}
Python:
a, b, c, d, e, f = map(float, input("a,b,c,d,e,f を入力してください: ").split())
D = a*e - b*d
Dx = c*e - b*f
Dy = a*f - c*d
if abs(D) < 1e-9:
if abs(Dx) < 1e-9 and abs(Dy) < 1e-9:
print("無限の解")
else:
print("解なし")
else:
x = Dx / D
y = Dy / D
print("x =", x, "y =", y)
4. 三次方程式 (ax³ + bx² + cx + d = 0)
解き方 (数学):
- 一般的な方法: カルダノの公式を使用します。
- x²項を取り除くために代入: x = t - b/(3a) とします。
- 簡略化された形: t³ + pt + q = 0.
- 判別式: Δ = (q/2)² + (p/3)³. Δ > 0 の場合: 1つの実根、2つの複素根。
Δ = 0 の場合: 少なくとも2つの等しい実根。
Δ < 0 の場合: 3つの異なる実根。
- Δ > 0 の場合: 1つの実根、2つの複素根。
- Δ = 0 の場合: 少なくとも2つの等しい実根。
- Δ < 0 の場合: 3つの異なる実根。
- 正直、C++ でカルダノの公式をコーディングするのは少し大変です。Python では NumPy を使うだけで済みます。
C++ (1つの実根のために簡略化):
#include <iostream>
#include <cmath>
using namespace std;
int main() {
double a,b,c,d;
cin >> a >> b >> c >> d;
double f = ((3*c/a) - (b*b)/(a*a)) / 3;
double g = ((2*b*b*b)/(a*a*a) - (9*b*c)/(a*a) + (27*d/a)) / 27;
double h = g*g/4 + f*f*f/27;
if (h > 0) {
double R = -(g/2) + sqrt(h);
double S = cbrt(R);
double T = -(g/2) - sqrt(h);
double U = cbrt(T);
double x1 = (S+U) - (b/(3*a));
cout << "1つの実根 x = " << x1 << "\n";
} else {
cout << "複数の実根 (完全なカルダノが必要)\n";
}
}
Python (NumPy):
import numpy as np
coeffs = list(map(float, input("a, b, c, d を入力してください: ").split()))
roots = np.roots(coeffs)
print("根:", roots)
結論
線形、二次、2×2 の連立方程式、三次方程式を解くための数学とコードをカバーしました。C++ は手動で公式を構築しますが、Python は簡潔に保ちます (NumPy は三次根を簡単に見つけます)。各ソルバーを自分で実装して、代数とプログラミングスキルを向上させてみてください。