#07 ふれてみよう高校数学 代数と式の操作

複素数の四則演算

複素数の加法・減法

3+2i3 + 2i14i1 - 4i を足す」——実部どうし、虚部どうしを別々に計算するだけです。ちょうど「りんご3個とみかん2個」を「りんご1個とみかん4個」に足すと「りんご4個とみかん6個」になるのと同じ感覚です。

z1=a+biz_1 = a + biz2=c+diz_2 = c + di のとき:

z₁ + z₂ = (a+c) + (b+d)i   ← 実部どうし、虚部どうしを足す
z₁ - z₂ = (a-c) + (b-d)i   ← 実部どうし、虚部どうしを引く

複素数平面上ではベクトルの加法と同じです——2つの矢印を「つなげる」操作です。

(3+2i)+(14i)=42i(3 + 2i) + (1 - 4i) = 4 - 2i

(5+i)(2+3i)=32i(5 + i) - (2 + 3i) = 3 - 2i


複素数の乗法

(a+bi)(c+di)(a + bi)(c + di) を普通に展開します。普通の式の展開(FOIL法)と同じですが、i2=1i^2 = -1 という置き換えが加わります。

(a + bi)(c + di) = ac + adi + bci + bdi²
                 = ac + adi + bci - bd
                 = (ac - bd) + (ad + bc)i

i2i^2 が出てきたら 1-1 に置き換える」——これだけ覚えれば計算できます。

(2+3i)(1i)(2 + 3i)(1 - i)

= 2·1 + 2·(-i) + 3i·1 + 3i·(-i)
= 2 - 2i + 3i - 3i²
= 2 + i + 3
= 5 + i

乗法の幾何学的意味:回転と拡大縮小

「掛け算が回転になる?」——直感的にはわかりにくいですが、極形式を使うと一目瞭然です。

z=r(cosθ+isinθ)z = r(\cos\theta + i\sin\theta) という「距離 rr、角度 θ\theta」の表し方(極形式)で乗法を考えると:

z1z2=r1r2[cos(θ1+θ2)+isin(θ1+θ2)]z_1 z_2 = r_1 r_2 [\cos(\theta_1 + \theta_2) + i\sin(\theta_1 + \theta_2)]

つまり:

  • 絶対値は掛け算z1z2=z1z2|z_1 z_2| = |z_1| \cdot |z_2|(距離が倍になる)
  • 偏角は足し算arg(z1z2)=arg(z1)+arg(z2)\arg(z_1 z_2) = \arg(z_1) + \arg(z_2)(角度が回転する)

ii を掛けることは 90° 回転

i=0+1i=1(cos90°+isin90°)i = 0 + 1 \cdot i = 1 \cdot (\cos 90° + i\sin 90°) なので、偏角が +90°+90° されます。「ii を1回掛けるたびに反時計回りに四分の一回転」——これが虚数単位の幾何学的正体です。

1 → ×i → i → ×i → -1 → ×i → -i → ×i → 1
複素数の乗算 = 回転 + 拡大縮小:自動アニメーションで掛け算の軌跡を見る
var t = 0;

function loop() {
ctx.clearRect(0, 0, W, H);
t += 0.012;

var cx = W/2, cy = H/2;
var scale = 65;

// Grid
ctx.strokeStyle = '#1a2744';
ctx.lineWidth = 1;
for (var gx = -4; gx <= 4; gx++) {
  ctx.beginPath(); ctx.moveTo(cx+gx*scale,0); ctx.lineTo(cx+gx*scale,H); ctx.stroke();
}
for (var gy = -3; gy <= 3; gy++) {
  ctx.beginPath(); ctx.moveTo(0,cy+gy*scale); ctx.lineTo(W,cy+gy*scale); ctx.stroke();
}

// Axes
ctx.strokeStyle = '#334155';
ctx.lineWidth = 1.5;
ctx.beginPath(); ctx.moveTo(0,cy); ctx.lineTo(W,cy); ctx.stroke();
ctx.beginPath(); ctx.moveTo(cx,0); ctx.lineTo(cx,H); ctx.stroke();

// z₁ = 1.5 (cos 30° + i sin 30°) - fixed
var r1 = 1.5, theta1 = 30 * Math.PI / 180;
var z1a = r1 * Math.cos(theta1), z1b = r1 * Math.sin(theta1);

// z₂ = 1.2 (cos θ + i sin θ) - animated angle
var r2 = 1.2, theta2 = t;
var z2a = r2 * Math.cos(theta2), z2b = r2 * Math.sin(theta2);

// product
var r3 = r1 * r2, theta3 = theta1 + theta2;
var z3a = r3 * Math.cos(theta3), z3b = r3 * Math.sin(theta3);

function drawVec(a, b, color, label, labelRight) {
  var px = cx + a * scale, py = cy - b * scale;
  ctx.strokeStyle = color;
  ctx.lineWidth = 2.5;
  ctx.beginPath();
  ctx.moveTo(cx, cy);
  ctx.lineTo(px, py);
  ctx.stroke();
  // arrowhead
  var angle = Math.atan2(-b, a);
  ctx.fillStyle = color;
  ctx.beginPath();
  ctx.moveTo(px, py);
  ctx.lineTo(px - 9*Math.cos(angle-0.4), py - 9*Math.sin(angle-0.4));
  ctx.lineTo(px - 9*Math.cos(angle+0.4), py - 9*Math.sin(angle+0.4));
  ctx.closePath();
  ctx.fill();
  // point
  ctx.beginPath();
  ctx.arc(px, py, 5, 0, Math.PI*2);
  ctx.fill();
  // label
  ctx.font = 'bold 13px monospace';
  ctx.textAlign = labelRight ? 'left' : 'right';
  ctx.fillText(label, px + (labelRight ? 8 : -8), py - 8);
}

drawVec(z1a, z1b, '#3b82f6', 'z₁', true);
drawVec(z2a, z2b, '#22c55e', 'z₂', z2a >= 0);
drawVec(z3a, z3b, '#f59e0b', 'z₁·z₂', z3a >= 0);

// Angle arcs
ctx.strokeStyle = '#3b82f6'; ctx.lineWidth = 1.5;
ctx.beginPath(); ctx.arc(cx, cy, 25, -theta1, 0, false); ctx.stroke();
ctx.strokeStyle = '#22c55e';
ctx.beginPath(); ctx.arc(cx, cy, 38, -theta2, 0, theta2 < 0); ctx.stroke();
ctx.strokeStyle = '#f59e0b';
ctx.beginPath(); ctx.arc(cx, cy, 52, -theta3, 0, theta2 < 0); ctx.stroke();

// Info
ctx.fillStyle = '#0f172a';
ctx.fillRect(8, 8, 230, 100);
ctx.strokeStyle = '#334155'; ctx.lineWidth = 1; ctx.strokeRect(8, 8, 230, 100);

ctx.font = '12px monospace'; ctx.textAlign = 'left';
ctx.fillStyle = '#93c5fd';
ctx.fillText('z₁: r=' + r1.toFixed(2) + ' θ=' + (theta1*180/Math.PI).toFixed(1) + '°', 18, 28);
ctx.fillStyle = '#86efac';
ctx.fillText('z₂: r=' + r2.toFixed(2) + ' θ=' + (theta2*180/Math.PI).toFixed(1) + '°', 18, 46);
ctx.fillStyle = '#fde68a';
ctx.fillText('積:  r=' + r3.toFixed(2) + ' θ=' + (theta3*180/Math.PI).toFixed(1) + '°', 18, 64);
ctx.fillStyle = '#94a3b8';
ctx.fillText('r₁×r₂=' + (r1*r2).toFixed(2) + '  θ₁+θ₂=' + ((theta1+theta2)*180/Math.PI).toFixed(1) + '°', 18, 82);
ctx.fillStyle = '#fbbf24';
ctx.fillText('偏角 = 足し算!  絶対値 = 掛け算!', 18, 100);

requestAnimationFrame(loop);
}
loop();

複素数の除法

z1/z2z_1 / z_2 は分母を「実数化」します——前回学んだ有理化(共役を使う)と全く同じ発想です:

z1z2=a+bic+di=(a+bi)(cdi)(c+di)(cdi)=(ac+bd)+(bcad)ic2+d2\dfrac{z_1}{z_2} = \dfrac{a+bi}{c+di} = \dfrac{(a+bi)(c-di)}{(c+di)(c-di)} = \dfrac{(ac+bd) + (bc-ad)i}{c^2+d^2}

3+i1+2i=(3+i)(12i)(1+2i)(12i)=36i+i2i21+4=55i5=1i\dfrac{3+i}{1+2i} = \dfrac{(3+i)(1-2i)}{(1+2i)(1-2i)} = \dfrac{3-6i+i-2i^2}{1+4} = \dfrac{5-5i}{5} = 1-i

極形式では: z1z2=r1r2[cos(θ1θ2)+isin(θ1θ2)]\dfrac{z_1}{z_2} = \dfrac{r_1}{r_2}[\cos(\theta_1 - \theta_2) + i\sin(\theta_1 - \theta_2)]

除法は偏角を引き算し、絶対値を割り算します——掛け算と逆の操作です。


ii のべき乗の周期性

ii を何回掛けても4種類しかない」という面白い性質があります。時計の時針のように一周して元に戻るのです。

ii のべき乗は周期 4 で繰り返します:

nnini^n
01
1ii
21-1
3i-i
411
5ii
\vdots\vdots

一般に in=inmod4i^n = i^{n \bmod 4}。「4で割った余りで決まる」——これだけ覚えれば大きなべき乗も計算できます。

例:i2026=i2026mod4=i2=1i^{2026} = i^{2026 \bmod 4} = i^2 = -12026=506×4+22026 = 506 \times 4 + 2

i の掛け算 = 90° 回転:4回掛けると元に戻る様子を確認
var t = 0;

function loop() {
ctx.clearRect(0, 0, W, H);
t += 0.02;

var cx = W/2, cy = H/2;
var scale = 80;

// Axes
ctx.strokeStyle = '#334155';
ctx.lineWidth = 1.5;
ctx.beginPath(); ctx.moveTo(0,cy); ctx.lineTo(W,cy); ctx.stroke();
ctx.beginPath(); ctx.moveTo(cx,0); ctx.lineTo(cx,H); ctx.stroke();

// Unit circle
ctx.strokeStyle = '#1e293b';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.arc(cx, cy, scale, 0, Math.PI * 2);
ctx.stroke();

var points = [
  { a: 1, b: 0, label: '1 = i⁰', color: '#3b82f6' },
  { a: 0, b: 1, label: 'i = i¹', color: '#22c55e' },
  { a: -1, b: 0, label: '-1 = i²', color: '#ef4444' },
  { a: 0, b: -1, label: '-i = i³', color: '#f59e0b' }
];

// Rotation highlight
var currentIdx = Math.floor((t / (Math.PI / 2)) % 4);
var frac = (t % (Math.PI / 2)) / (Math.PI / 2);

for (var i = 0; i < points.length; i++) {
  var p = points[i];
  var px = cx + p.a * scale;
  var py = cy - p.b * scale;

  ctx.fillStyle = i === currentIdx ? p.color : p.color + '66';
  ctx.beginPath();
  ctx.arc(px, py, i === currentIdx ? 12 : 7, 0, Math.PI*2);
  ctx.fill();

  ctx.font = 'bold 12px monospace';
  ctx.fillStyle = p.color;
  ctx.textAlign = p.a > 0 ? 'left' : (p.a < 0 ? 'right' : 'center');
  var ly = p.b > 0 ? py - 16 : (p.b < 0 ? py + 22 : py - 16);
  ctx.fillText(p.label, px + (p.a !== 0 ? p.a*14 : 0), ly);
}

// Animated arrow
var angle = -t;
var ax = cx + Math.cos(angle) * scale;
var ay = cy + Math.sin(angle) * scale;
ctx.strokeStyle = '#fbbf24';
ctx.lineWidth = 2.5;
ctx.beginPath();
ctx.moveTo(cx, cy);
ctx.lineTo(ax, ay);
ctx.stroke();
ctx.fillStyle = '#fbbf24';
ctx.beginPath();
ctx.arc(ax, ay, 6, 0, Math.PI*2);
ctx.fill();

ctx.fillStyle = '#94a3b8';
ctx.font = '13px monospace';
ctx.textAlign = 'center';
ctx.fillText('× i ごとに 90° 回転  →  4回で一周', W/2, H - 14);

requestAnimationFrame(loop);
}
loop();

ド・モアブルの定理

(cosθ+isinθ)n=cos(nθ)+isin(nθ)(\cos\theta + i\sin\theta)^n = \cos(n\theta) + i\sin(n\theta)

これを使うと nn 乗の計算が偏角の nn 倍になります——「複素数を nn 乗する = 角度を nn 倍する」という美しいルールです。

例:(1+i)8(1 + i)^8 を計算する

1+i=2(cos45°+isin45°)1 + i = \sqrt{2}(\cos 45° + i\sin 45°) なので:

(1+i)8=(2)8(cos360°+isin360°)=161=16(1+i)^8 = (\sqrt{2})^8 (\cos 360° + i\sin 360°) = 16 \cdot 1 = 16


まとめ

演算直交形式極形式
加法実部・虚部それぞれ足す複雑(使わない)
乗法(acbd)+(ad+bc)i(ac-bd)+(ad+bc)ir1r2r_1 r_2θ1+θ2\theta_1+\theta_2
除法共役で有理化r1/r2r_1/r_2θ1θ2\theta_1-\theta_2
nn面倒ド・モアブルの定理
  • 乗法 = 回転 + 拡大縮小という幾何学的な見方が最も重要——「掛け算が回転」という驚きの事実
  • ii を掛けることは 90° 反時計回りの回転

次回は方程式の基本に戻り、1次・連立方程式の解き方を整理します。