//: [Previous](@previous) // Xcode で Editor メニュー > Show Render Markup でお読みください //import UIKit /*: # 中学2年の数学 */ /*: ## 連立方程式 */ do { // 例題17、あたりをつけるやり方(本来、こんなことはしない) let a = 2.0, b = 3.0, c = 30.0 let d = 1.0, e = -1.0, f = -5.0 for v in [ [Double?]([ 1.0, nil ]), [Double?]([ 2.0, nil ]), [Double?]([ 3.0, nil ]), [Double?]([ nil, 6.0 ]), [Double?]([ nil, 4.0 ]), ] { var x = 0.0, y = 0.0 if v[0] != nil { x = v[0]! y = (c - a*x)/b } else if v[1] != nil { y = v[1]! x = (c - b*y)/a } let y2 = (f - d*x)*e print("𝑥=\(x), 𝑦=\(y), (2) 𝑦=\(y2), \(y == y2 ? "正解" : "不正解")") } /* x=1.0, y=9.333333333333334, (2) y=6.0, 不正解 x=2.0, y=8.666666666666666, (2) y=7.0, 不正解 x=3.0, y=8.0, (2) y=8.0, 正解 x=6.0, y=6.0, (2) y=11.0, 不正解 x=9.0, y=4.0, (2) y=14.0, 不正解 */ } /* 𝑎𝑥 + 𝑏𝑦 = 𝑐 … (1) 𝑑𝑥 + 𝑒𝑦 = 𝑓 … (2) の連立方程式を解く 式(2)×𝑎/𝑑 𝑎/𝑑⋅𝑑𝑥 + 𝑎/𝑑⋅𝑒𝑦 = 𝑎/𝑑⋅𝑓 𝑎𝑥 + 𝑎/𝑑⋅𝑒𝑦 = 𝑎/𝑑⋅𝑓 … (2') 𝑎𝑥 + 𝑏𝑦 = 𝑐 … (1) (2')-(1) 𝑎/𝑑⋅𝑒𝑦 - 𝑏𝑦 = 𝑎/𝑑⋅𝑓 - 𝑐 (𝑎/𝑑⋅𝑒 - 𝑏)𝑦 = 𝑎/𝑑⋅𝑓 - 𝑐 𝑦 = (𝑎𝑓/𝑑 - 𝑐)/(𝑎𝑒/𝑑 - 𝑏) = 𝑑(𝑎𝑓/𝑑 - 𝑐)/(𝑑(𝑎𝑒/𝑑 - 𝑏)) = (𝑎𝑓 - 𝑐𝑑)/(𝑎𝑒 - 𝑏𝑑) … (3) 式(1)に式(3)を代入 𝑎𝑥 + 𝑏((𝑎𝑓 - 𝑐𝑑)/(𝑎𝑒 - 𝑏𝑑)) = 𝑐 𝑎𝑥 = 𝑐 - 𝑏((𝑎𝑓 - 𝑐𝑑)/(𝑎𝑒 - 𝑏𝑑)) 𝑥 = 𝑐/𝑎 - 𝑏((𝑎𝑓 - 𝑐𝑑)/(𝑎𝑒 - 𝑏𝑑))/𝑎 = 𝑐/𝑎 - (𝑎𝑏𝑓 - 𝑏𝑐𝑑)/(𝑎^2𝑒 - 𝑎𝑏𝑑) … (4) */ do { // 例題17 let a = 2.0, b = 3.0, c = 30.0 let d = 1.0, e = -1.0, f = -5.0 let x = c/a - (a*b*f - b*c*d)/(a*a*e - a*b*d) let y = (a*f - c*d)/(a*e - b*d) print("𝑥=\(x), 𝑦=\(y)") // x=3.0, y=8.0 } do { // 練習17 let a = 2.0, b = 1.0, c = 10.0 let d = 1.0, e = 1.0, f = 7.0 let x = c/a - (a*b*f - b*c*d)/(a*a*e - a*b*d) let y = (a*f - c*d)/(a*e - b*d) print("𝑥=\(x), 𝑦=\(y)") // x=3.0, y=4.0 } /* 𝑎𝑥 + 𝑏𝑦 = 𝑐 … (1) 𝑑𝑥 + 𝑒𝑦 = f … (2) の連立方程式を解く、別解 式(1)×𝑑/𝑎 𝑑/𝑎⋅𝑎𝑥 + 𝑑/𝑎⋅𝑏𝑦 = 𝑑/𝑎⋅𝑐 𝑑𝑥 + 𝑑/𝑎⋅𝑏𝑦 = 𝑑/𝑎⋅𝑐 … (1') 𝑑𝑥 + 𝑒𝑦 = 𝑓 … (2) (1')-(2) 𝑑/𝑎⋅𝑏𝑦 - 𝑒𝑦 = 𝑑/𝑎⋅𝑐 - 𝑓 (𝑑/𝑎⋅𝑏 - 𝑒)𝑦 = 𝑑/𝑎⋅𝑐 - 𝑓 𝑦 = (𝑑/𝑎⋅𝑐 - 𝑓)/(𝑑/𝑎⋅𝑏 - 𝑒) = 𝑎(𝑑/𝑎⋅𝑐 - 𝑓)/(𝑎(𝑑/𝑎⋅𝑏 - 𝑒)) = (𝑐𝑑 - 𝑎𝑓)/(𝑏𝑑 - 𝑎𝑒) … (3) 式(2)に式(3)を代入 𝑑𝑥 + 𝑒((𝑐𝑑 - 𝑎𝑓)/(𝑏𝑑 - 𝑎𝑒)) = 𝑓 𝑑𝑥 = 𝑓 - 𝑒((𝑐𝑑 - 𝑎𝑓)/(𝑏𝑑 - 𝑎𝑒)) 𝑥 = 𝑓/𝑑 - 𝑒((𝑐𝑑 - 𝑎𝑓)/(𝑏𝑑 - 𝑎𝑒))/𝑑 = 𝑓/𝑑 - (𝑐𝑑𝑒- 𝑎𝑒𝑓)/(𝑏𝑑^2 - 𝑎𝑑𝑒) */ do { // 例題17 let a = 2.0, b = 3.0, c = 30.0 let d = 1.0, e = -1.0, f = -5.0 let x = f/d - (c*d*e - a*e*f)/(b*d*d - a*d*e) let y = (c*d - a*f)/(b*d - a*e) print("𝑥=\(x), 𝑦=\(y)") // x=3.0, y=8.0 } do { // 練習17 let a = 2.0, b = 1.0, c = 10.0 let d = 1.0, e = 1.0, f = 7.0 let x = f/d - (c*d*e - a*e*f)/(b*d*d - a*d*e) let y = (c*d - a*f)/(b*d - a*e) print("𝑥=\(x), 𝑦=\(y)") // x=3.0, y=4.0 } print("連立方程式: 連立方程式(a:_b:_c:_d:_e:_f:_) を用いる") //: この手続きを関数にして、再利用可能にする func 連立方程式(a: Double, b: Double, c: Double, d: Double, e: Double, f: Double) -> (x: Double, y: Double) { return (x: c/a - (a*b*f - b*c*d)/(a*a*e - a*b*d), y: (a*f - c*d)/(a*e - b*d)) // 解なしのときは (inf, inf) を返す } do { for (x, y) in [ // 例題18 連立方程式(a: 1.0, b: -3.0, c: 7.0, d: 2.0, e: 3.0, f: -4.0), 連立方程式(a: 1.0, b: 4.0, c: 17.0, d: 1.0, e: 2.0, f: 11.0), 連立方程式(a: 2.0, b: -3.0, c: 4.0, d: 3.0, e: -7.0, f: 5.0), // 練習18 連立方程式(a: 1.0, b: 1.0, c: 3.0, d: 3.0, e: -1.0, f: -9.0), 連立方程式(a: 3.0, b: -2.0, c: -1.0, d: 3.0, e: 4.0, f: 11.0), 連立方程式(a: 5.0, b: -3.0, c: 2.0, d: 7.0, e: -4.0, f: 3.0), // 例題19 連立方程式(a: 2.0, b: -3.0, c: -7.0, d: 1.0, e: 1.0, f: 9.0), 連立方程式(a: 1.0, b: 2.0, c: 3.0, d: 2.0, e: -1.0, f: -4.0), 連立方程式(a: 1.0, b: -1.0, c: 8.0, d: 2.0, e: 1.0, f: 7.0), // 練習19 連立方程式(a: 7.0, b: -1.0, c: 1.0, d: -3.0, e: -1.0, f: -4.0), 連立方程式(a: 2.0, b: -1.0, c: -4.0, d: 3.0, e: 2.0, f: 15.0), // 応用 連立方程式(a: 1.0, b: 1.0, c: 1.0, d: 1.0, e: 1.0, f: -1.0), ] { print("𝑥=\(x), 𝑦=\(y)") } /* x=1.0, y=-2.0 x=5.0, y=3.0 x=2.6, y=0.4 x=-1.5, y=4.5 x=1.0, y=2.0 x=1.0, y=1.0 x=4.0, y=5.0 x=-1.0, y=2.0 x=5.0, y=-3.0 x=0.5, y=2.5 x=1.0, y=6.0 x=inf, y=-inf */ } print("逆数の連立方程式: 逆数の連立方程式(a:_b:_c:_d:_e:_f:_) を用いる") //: この手続きを関数にして、再利用可能にする func 逆数の連立方程式(a: Double, b: Double, c: Double, d: Double, e: Double, f: Double) -> (x: Double, y: Double) { let (x, y) = 連立方程式(a: a, b: b, c: c, d: d, e: e, f: f) return (x: 1.0/x, y: 1.0/y) // } do { for (x, y) in [ // 例題23 逆数の連立方程式(a: 3.0, b: 2.0, c: 17.0, d: 4.0, e: -5.0, f: -8.0), // 練習23 逆数の連立方程式(a: 1.0, b: 1.0, c: 5.0, d: 2.0, e: -5.0, f: -11.0), // 応用 逆数の連立方程式(a: 1.0, b: 1.0, c: 1.0, d: 1.0, e: 1.0, f: -1.0), ] { print("𝑥=\(x), 𝑦=\(y)") } /* x=0.33333333333333326, y=0.25 x=0.5, y=0.3333333333333333 x=0.0, y=-0.0 */ } /* 解から係数を求める 𝑎𝑥 - 𝑏𝑦 = 𝑐 … (1) 𝑏𝑥 + 𝑎𝑦 = 𝑑 … (2) の連立方程式において解𝑥, 𝑦が与えられたときの𝑎, 𝑏を求める 𝑥𝑎 - 𝑦𝑏 = 𝑐 … (1) 𝑦𝑎 + 𝑥𝑏 = 𝑑 … (2) 式(2)×𝑥/𝑦 𝑥/𝑦⋅𝑦𝑎 + 𝑥/𝑦⋅𝑥𝑏 = 𝑥/𝑦⋅𝑑 𝑥𝑎 + 𝑥^2/𝑦𝑏 = 𝑥/𝑦⋅𝑑… (2') 𝑥𝑎 - 𝑦𝑏 = 𝑐 … (1) (2')-(1) 𝑥^2/𝑦𝑏 + 𝑦𝑏 = 𝑥/𝑦⋅𝑑 - 𝑐 (𝑥^2/𝑦 + 𝑦)𝑏 = 𝑥/𝑦⋅𝑑 - 𝑐 𝑏 = (𝑥/𝑦⋅𝑑 - 𝑐)/(𝑥^2/𝑦 + 𝑦) = 𝑦(𝑥/𝑦⋅𝑑 - 𝑐)/(𝑦(𝑥^2/𝑦 + 𝑦)) = (𝑥𝑑 - 𝑦𝑐)/(𝑥^2 + 𝑦^2) … (3) 式(1)に式(3)を代入 𝑥𝑎 - 𝑦(𝑥𝑑 - 𝑦𝑐)/(𝑥^2 + 𝑦^2) = 𝑐 𝑥𝑎 = 𝑐 + 𝑦(𝑥𝑑 - 𝑦𝑐)/(𝑥^2 + 𝑦^2) 𝑎 = 𝑐/𝑥 + 𝑦(𝑥𝑑 - 𝑦𝑐)/(𝑥^3 + 𝑥𝑦^2) */ print("連立方程式と解から係数を求める(1)") do { let x = 3.0, y = 5.0, c = -9.0, d = 19.0 let a = c/x + y*(x*d - y*c)/(x*x*x + x*y*y) let b = (x*d - y*c)/(x*x + y*y) print("𝑎=\(a), 𝑏=\(b)") // a=2.0, b=3.0 } /* 解から係数を求める 𝑏𝑥 + 𝑑𝑦 = 𝑎 … (1) 𝑐𝑥 + 𝑎𝑦 = 5𝑏 … (2) の連立方程式において解𝑥, 𝑦が与えられたときの𝑎, 𝑏を求める 𝑎 - 𝑥𝑏 = 𝑑𝑦 … (1) -𝑦𝑎 + 5𝑏 = 𝑐𝑥… (2) 式(2)×(-1/𝑦) 𝑎 - 1/𝑦⋅5𝑏 = -1/𝑦⋅𝑐𝑥 … (2') 𝑎 - 𝑥𝑏 = 𝑑𝑦 … (1) (2')-(1) -1/𝑦⋅5𝑏 + 𝑥𝑏 = -1/𝑦⋅𝑐𝑥 - 𝑑𝑦 (-1/𝑦⋅5 + 𝑥)𝑏 = -1/𝑦⋅𝑐𝑥 - 𝑑𝑦 𝑏 = (-1/𝑦⋅𝑐𝑥 - 𝑑𝑦)/(-1/𝑦⋅5 + 𝑥) = 𝑦(-1/𝑦⋅𝑐𝑥 - 𝑑𝑦)/(𝑦(-1/𝑦⋅5 + 𝑥)) = (-𝑐𝑥 - 𝑑𝑦^2)/(-5 + 𝑥𝑦) … (3) 式(1)に式(3)を代入 𝑎 - 𝑥(-𝑐𝑥 - 𝑑𝑦^2)/(-5 + 𝑥𝑦) = 𝑑𝑦 𝑎 = 𝑑𝑦 + 𝑥(-𝑐𝑥 - 𝑑𝑦^2)/(-5 + 𝑥𝑦) */ print("連立方程式と解から係数を求める(2)") do { let x = 1.0, y = -1.0, c = 2.0, d = 4.0 let a = d*y + x*(-c*x - d*y*y)/(-5 + x*y) let b = (-c*x - d*y*y)/(-5 + x*y) print("𝑎=\(a), 𝑏=\(b)") // a=-3.0, b=1.0 } /*: ### 発展 連立3元一次方程式 2𝑥 - 𝑦 - 𝑧 = 5 3𝑥 + 2𝑦 + 4𝑧 = 2 4𝑥 + 3𝑦 + 2𝑧 = -2 を解きなさい #### 大学への数学 大学では線形代数を学び、以上は「行列とベクトル」を用いて以下のように表されます 𝑨𝒙 = 𝒃 ⇔ [ 2 -1 -1 ][𝑥] [ 5] [ 3 2 4 ][𝑦] = [ 2] [ 4 3 2 ][𝑧] [-2] かぎ括弧は、本来3行にわたり縦に長い一つの括弧です。Playground では数式が表せないので以上のように表します。 定数 𝑨 は 3×3 の行列、変数 𝒙 は3要素の縦ベクトル、定数 𝒃 は3要素の縦ベクトルです 要素数 3 を 𝑛 として、任意の要素数の1次方程式を解くことも可能です。これを連立 𝑛 元一次方程式といいます そのとき用いられるアルゴリズムとして「ガウスの消去法」が挙げられます。手計算の手順と変わらないことがわかると思います */ func ガウスの消去法(A: [[Double]], b: [Double]) -> (A: [[Double]], x: [Double]) { let n = b.count var A = A, x = b var t = 0.0 for k in 0 ..< n - 1 { for i in k + 1 ..< n { t = A[i][k] / A[k][k] for j in k + 1 ..< n { A[i][j] -= t * A[k][j] } x[i] -= t * x[k] } } for i in stride(from: n - 1, through: 0, by: -1) { t = x[i] for j in i + 1 ..< n { t -= A[i][j] * x[j] } x[i] = t / A[i][i] } return (A: A, x: x) } do { for (A, b) in [ ([ [ 2.0, -1.0, -3.0 ], [ 3.0, 2.0, 4.0 ], [ 4.0, 3.0, 2.0 ], ], [ 5.0, 2.0, -2.0 ] ), // 例題35 ([ [ 2.0, -3.0, -1.0 ], [ 5.0, 2.0, -3.0 ], [ 2.0, -4.0, -5.0 ], ], [ 3.0, -3.0, -4.0 ] ), // 練習35 ([ [ 1.0, 1.0, 0.0 ], [ 0.0, 1.0, 1.0 ], [ 1.0, 0.0, 1.0 ], ], [ -3.0, -1.0, 10.0 ] ), ] { print(A, ガウスの消去法(A: A, b: b)) } /* 以下のベクトル x が解 [[2.0, -1.0, -3.0], [3.0, 2.0, 4.0], [4.0, 3.0, 2.0]] (A: [[2.0, -1.0, -3.0], [3.0, 3.5, 8.5], [4.0, 5.0, -4.142857142857142]], x: [2.0, -4.0, 1.0]) [[2.0, -3.0, -1.0], [5.0, 2.0, -3.0], [2.0, -4.0, -5.0]] (A: [[2.0, -3.0, -1.0], [5.0, 9.5, -0.5], [2.0, -1.0, -4.052631578947368]], x: [1.0, -1.0, 2.0]) [[1.0, 1.0, 0.0], [0.0, 1.0, 1.0], [1.0, 0.0, 1.0]] (A: [[1.0, 1.0, 0.0], [0.0, 1.0, 1.0], [1.0, -1.0, 2.0]], x: [4.0, -7.0, 6.0]) */ } //: [Next](@next)