エクセル雑感
ITエンジニアなら知らないと恥ずかしい数学20選

ExcelマクロVBAとエクセル関数についての私的雑感
公開日:2026-09-17 最終更新日:2026-09-17

ITエンジニアなら知らないと恥ずかしい数学20選


ITエンジニアなら知らないと恥ずかしい数学20選

「ITエンジニアなら知らないと恥ずかしい数学20選」――少し挑発的なタイトルにしました。
ではなぜ、あえてここまで強い言葉を使って、ITエンジニアに数学の必要性を訴えるのでしょうか。


それは、数学がITの現場で生きているからです。

条件分岐には論理があり、データの分類には集合があります。
処理の依存関係にはグラフがあり、アルゴリズムの速さには計算量があります。
確率・統計、行列、ベクトル、微分といった数学も、データ分析、機械学習、検索、画像処理など、さまざまなIT技術の中で使われています。

もちろん、数学を知らなくてもコードを書くことはできます。
しかし数学を知ると、ただ動いているだけに見えていたコードの背後に、「なぜそうなるのか」という構造が見えてきます。

大切なのは、数学を学校の勉強だけで終わらせないことです。
学んだ数学を、ITの現場で生かす。
そして、普段のコードやシステムの中にある数学を見つける。
その往復によって、数学もITも、より深く理解できるようになります。

本稿の目的は、難しい公式を暗記することではありません。
ITの中に隠れている構造を見つけるための「数学のメガネ👓」を増やすことです。

本稿では、数ある数学の中から、「その数学を知ることで、ITの見え方が変わるか」という基準で20の概念を取り上げます。
数学そのものを確認するコードと、IT実務の中で同じ数学がどのように生きているのかを、Python、VBA、JavaScriptのコードとともに見ていきます。

掲載コードについて
本稿に掲載しているコードは、数学とコンピュータサイエンス(CS)の橋渡しとして、数学的な考え方がプログラムの中でどのように現れるのかを示すためのサンプルです。
数学的な構造そのものを確認する例に加えて、同じ構造がIT実務のコードにどのように現れるかを示す「IT実務での例」も掲載しています。
実用的なツールや業務処理として使用することを目的としたものではなく、特定の用途にそのまま利用できることを想定したものでもありません。
掲載コードは、すべての環境での動作を保証するものではありません。
実際に使用する場合は、コードの内容を十分に確認し、必要に応じて修正・検証したうえで、自己責任でご利用ください。
特にVBAなど、実際のデータを変更する可能性があるコードを実行する場合は、事前にバックアップを取るなど、十分に注意してください。
掲載コードの使用によって、データの破損、消失その他の損害が発生した場合でも、当方では責任を負いかねます。


※Pythonのコードには、標準ライブラリ以外のライブラリ(NumPy、SciPyなど)を使用しているものがあります。実行には別途インストールが必要な場合があります。
※本記事の数式および解説文章の多くは、生成AIを活用して作成しました。数式動作や解説文の最終的な内容は人間による確認・編集を経て掲載しています。




ページ内目次



導入:なぜエンジニアに「数学のメガネ」が必要なのか

日々書いているコードの中には、すでに数学の構造が深く入り込んでいます。
条件分岐、繰り返し、状態管理、依存関係――こうしたプログラムの基本的な構造の背後には、離散数学や線形代数など、さまざまな数学的概念があります。


ここでいう「数学」とは、公式を暗記したり、難しい計算問題を解いたりすることではありません。
目の前の問題を別の角度から捉え、その背後にある構造や関係を見抜くための道具です。

「数学のメガネ」を持つことでコードの捉え方がどう変わるのか、2つの例で説明します。

例1:周期処理 ――「範囲外なら戻す」から「循環構造」へ

「0~11の盤面上を移動する」という処理を考えます。


Bad:手続き思考(状態を追いかける)

問題を「直線上の目盛り」と捉えると、境界を超えたかどうかを条件分岐やループで管理することになります。
def move(pos, step):
    pos += step
    while pos >= 12:
        pos -= 12
    while pos < 0:
        pos += 12
    return pos

Good:構造的思考(12を法とする合同算術)

問題を「12を法とする合同算術」として捉え直すと、12で一周する循環構造として扱うことができます。
def move(pos, step):
    return (pos + step) % 12
重要なのは「% 演算子を知っていたか」ではありません。
「範囲から外れたら手動で戻す」という手続き思考から、「この問題の本質は12で一周する循環構造である」という数学的モデルへ捉え直したことです。

例2:処理順序 ――「FlagとIf文」から「依存関係のグラフ」へ

次に、タスク間に依存関係がある場合を考えます。
「Aが終わったらBとCを実行し、BとCの両方が終わったらDを実行する」という処理です。


Bad:手続き思考(FlagとIf文で状態を管理する)

構造を意識せずに実装すると、各タスクが終了したかどうかをフラグで管理し、条件分岐を積み重ねることになります。
if not a_done:
    do_a()
    a_done = True

if a_done and not b_done:
    do_b()
    b_done = True

if a_done and not c_done:
    do_c()
    c_done = True

if b_done and c_done and not d_done:
    do_d()
    d_done = True

タスクが増えたり依存関係が複雑になったりすると、フラグとIf文も増えていきます。
しかし、この問題を「実行手順」としてではなく、「タスク同士の依存関係」として見ると、別の姿が見えてきます。

Good:構造的思考(有向非巡回グラフ)

この例は、タスクをノード、依存関係をエッジとする有向非巡回グラフ(DAG)として表現できます。
A ──→ B ──┐
│       │
└──→ C ──┴──→ D

この構造を、そのままデータとして表現してみます。

from graphlib import TopologicalSorter

tasks = {
    "A": [],
    "B": ["A"],
    "C": ["A"],
    "D": ["B", "C"]
}

order = list(TopologicalSorter(tasks).static_order())
print(order)

ここでは「Aを実行してからBを実行する」といった手順を直接コードに書いていません。
「BはAに依存する」「CはAに依存する」「DはBとCに依存する」という関係そのものを表現し、その構造から実行順序を導き出しています。


このような有向グラフから、依存関係を壊さずに処理できる順序を求める代表的な方法がトポロジカルソートです。

タスクが増えても、基本的に追加するのは「どのタスクに依存しているか」という関係です。
If文を増やして処理手順を管理するのではなく、問題そのものをグラフという数学的構造として表現し、その構造から必要な処理を導き出すのです。

本質:「どう処理するか」から「この問題は何なのか」へ

コードが短くなるのは結果に過ぎません。
本質は、問題を見るときのスタート地点が変わることにあります。

  • 手続き思考(メガネなし):「どうやって順に処理を実行させるか?」(If文、フラグ、状態管理)
  • 構造思考(数学のメガネ):「そもそも、この問題の背後にある構造は何なのか?」(周期、グラフ、集合)
目の前のIf文をどう減らすかではありません。
そもそも、なぜIf文が必要になっているのか。
問題の捉え方を変えることで、必要だった処理そのものが不要になることがあります。

数学とは、複雑に見える問題から、その背後にある構造や関係を取り出して見るためのメガネです。

日常のプログラミング 背後にある数学のメガネ(構造)
条件分岐や仕様の整理 命題論理・述語論理
重複排除やグループ化 集合論・同値関係
周期処理や巡回バッファ 合同算術
処理の依存関係やネットワーク経路 グラフ理論
処理速度・スケーラビリティの評価 計算量(オーダー表記)
不確実なデータやログからの推論 確率・統計・ベイズの定理
多次元データの変換 線形代数

ここから、ITエンジニアの世界観を変える20の数学概念を順に紐解いていきます。


第1章:構造を見る数学(01~06)

プログラムやデータベース、ネットワークの本質は「構造」です。
数値そのものではなく、条件の組み合わせ、対象同士の関係性、データの繋がりを捉えるための静的な数学のメガネを揃えます。

ここで扱う数学は、何かを計算するためだけのものではありません。
「何と何が同じなのか」「どの対象がどの対象と関係するのか」「どのような対応規則でデータが変換されるのか」といった、プログラムやデータの形そのものを記述するための数学です。
条件、集合、関係、写像、グラフ、代数的構造という見方を身につけると、別々のものに見えていたITの仕組みを、共通する構造として捉えられるようになります。

こうした考え方は、離散数学や論理学を基盤として、データ構造、データベース、アルゴリズムなど、コンピュータサイエンスのさまざまな分野につながっています。

01. 命題論理と述語論理

数学として何なのか(定義式)
真偽(True/False)が定まる文を「命題」といい、命題 P、Q に対して、論理積 P ∧ Q、論理和 P ∨ Q、否定 ¬P などの論理演算を定義します。
たとえば P ∧ Q は P と Q がともに真のときだけ真になります。
さらに、対象 x とその対象が満たす条件 P(x) を考え、∀x P(x)(すべての x について P(x) が成り立つ)や ∃x P(x)(ある x について P(x) が成り立つ)によって、条件が成立する対象の範囲を表します。
命題論理が「命題同士の組み合わせ」を扱うのに対し、述語論理では「対象」と「その対象についての条件」まで含めて論理を表現します。
直感的にはどういう構造なのか
命題論理では、「AかつB」「AまたはB」「Aではない」という条件の組み合わせを扱います。
述語論理では、さらに「すべてのデータが条件を満たす」「少なくとも1件は条件を満たす」というように、対象の集まりと条件の関係まで表せます。
つまり、単なる Yes / No の判定から一歩進んで、「何について」「どの条件が」「どの範囲で」成り立つのかを構造として記述する数学です。
IT(コード)ではどこに現れるのか
複雑な業務要件における複数のガード条件の組み合わせや、早期リターンを設計する際の論理構築にそのまま現れます。
これを知ると何が違って見えるのか(「数学のメガネ」として)
単なる分岐コードの羅列に見えていたものを、「仕様を表す論理式や条件の組み合わせ」として捉えられるようになります。
不要なネストや論理の破綻に気づきやすくなり、条件分岐をより整理された形で設計・見直すための判断材料になります。
実装例1
処理内容
全称判定・存在判定
ユーザー一覧について、「すべて有効か」「特定のユーザーが存在するか」を論理値として判定します。
Pythonでの実装例
users = [{"name": "Alice", "active": True}, {"name": "Bob", "active": True}]
all_active = all(u["active"] for u in users)
has_bob = any(u["name"] == "Bob" for u in users)
VBAでの実装例
Sub CheckLogic()
    Dim names As Variant, active As Variant
    Dim i As Long
    Dim allActive As Boolean, hasBob As Boolean

    names = Array("Alice", "Bob")
    active = Array(True, True)
    allActive = True
    hasBob = False

    For i = LBound(names) To UBound(names)
        If Not active(i) Then allActive = False
        If names(i) = "Bob" Then hasBob = True
    Next i

    Debug.Print allActive, hasBob
End Sub
JavaScriptでの実装例
const users = [
    { name: "Alice", active: true },
    { name: "Bob", active: true }
];

const allActive = users.every(u => u.active);
const hasBob = users.some(u => u.name === "Bob");

console.log(allActive, hasBob);
実装例2(IT実務での例)
処理内容
ユーザーの編集権限を判定する
ユーザーの状態・役割・停止フラグを組み合わせて、編集操作を許可するか判定します。
👓 数学のメガネ:業務上の権限判定も、P ∧ (Q ∨ R) ∧ ¬S のような命題の組み合わせとして整理できます。
Pythonでの実装例
user = {"active": True, "role": "editor", "suspended": False}

can_edit = (
    user["active"]
    and user["role"] in {"admin", "editor"}
    and not user["suspended"]
)

print(can_edit)
VBAでの実装例
Sub PermissionExample()
    Dim active As Boolean, suspended As Boolean
    Dim role As String
    Dim canEdit As Boolean

    active = True
    role = "editor"
    suspended = False

    canEdit = active And _
              (role = "admin" Or role = "editor") And _
              Not suspended

    Debug.Print canEdit
End Sub
JavaScriptでの実装例
const user = {
    active: true,
    role: "editor",
    suspended: false
};

const canEdit =
    user.active &&
    ["admin", "editor"].includes(user.role) &&
    !user.suspended;

console.log(canEdit);
補足:De Morgan(ド・モルガン)の法則
否定を含む複雑な条件式では、De Morganの法則がそのままコードの書き換えに使えます。
¬(P ∧ Q) = ¬P ∨ ¬Q、¬(P ∨ Q) = ¬P ∧ ¬Q です。
たとえば「有効かつ権限あり、ではない」という条件は、「無効、または権限なし」と同じ意味になります。
条件式の否定を展開したり、ガード節へ書き換えたりするときに、論理を崩さず整理するための実践的なルールです。

Python
not (is_active and has_permission)
# 同値
(not is_active) or (not has_permission)
VBA
Not (isActive And hasPermission)
' 同値
(Not isActive) Or (Not hasPermission)
JavaScript
!(isActive && hasPermission)
// 同値
!isActive || !hasPermission
👓 数学のメガネ:複雑な If 文の整理は、単なる書き方の工夫ではなく、論理式を同値な形へ変形する操作として捉えられます。

02. 関係と順序(同値関係・半順序)

数学として何なのか(定義式)
集合 X 上の二項関係 R を考えます。
xRy を「x と y の間に関係 R がある」と表し、関係がどのような性質を持つかを公理で分類します。
反射律 xRx、対称律 xRy ⇒ yRx、推移律 xRy かつ yRz ⇒ xRz を満たす関係を同値関係といいます。
一方、反射律、反対称律 xRy かつ yRx ⇒ x=y、推移律を満たす関係を半順序といいます。
同値関係では「同じとみなせるもの」を分類でき、半順序では「どちらが先・上位・包含関係にあるか」といった順序を表現できます。
直感的にはどういう構造なのか
同値関係は、「違うものだけれど、この基準では同じ仲間として扱える」という仕組みです。
半順序は、「集合Aは集合Bに含まれる」のように、すべての対象を一直線に並べられなくても、対象同士の順序関係を表せます。
「同じものとしてまとめる」と「順序を付ける」という処理が、関係の性質として数学的に整理できます。
IT(コード)ではどこに現れるのか
リレーショナルデータベースにおけるテーブルの結合キー設計や、タスク間に存在する前後依存関係を解決して実行順序を決定するトポロジカルソートなどの処理の根底に現れます。
これを知ると何が違って見えるのか(「数学のメガネ」として)
複雑に絡み合ったデータ構造や処理の依存関係の背後にある、「同値のクラス」や「実行順序を表す関係」が見えやすくなります。
関係性や依存順序を整理することで、設計上の矛盾や問題のある依存関係を発見しやすくなります。
実装例1
処理内容
グループ化(Group By)
データをキーごとに分類し、同じキーを持つ要素をまとめます。
Pythonでの実装例
from itertools import groupby
data = [("A", 1), ("A", 2), ("B", 3)]
for key, group in groupby(data, lambda x: x[0]):
    print(key, list(group))

※ itertools.groupby は、同じキーの要素が連続している範囲をグループ化します。キーの順序を問わず同じキーの要素をまとめたい場合は、あらかじめキーでソートしておく必要があります。

VBAでの実装例
Sub GroupExample()
    Dim dict As Object
    Dim groups As Collection
    Dim keys As Variant
    Dim i As Long
    Dim key As String
    Dim value As Variant
    Set dict = CreateObject("Scripting.Dictionary")
    For i = 1 To 3
        If i < 3 Then
            key = "A"
        Else
            key = "B"
        End If
        value = i
        If Not dict.Exists(key) Then
            Set groups = New Collection
            dict.Add key, groups
        End If
        Set groups = dict(key)
        groups.Add value
    Next i
    keys = dict.keys
    For i = LBound(keys) To UBound(keys)
        Set groups = dict(keys(i))
        Debug.Print keys(i) & ":"
        For Each value In groups
            Debug.Print " " & value
        Next value
    Next i
End Sub
JavaScriptでの実装例
const data = [["A", 1], ["A", 2], ["B", 3]];

const grouped = data.reduce((acc, [key, value]) => {
    if (!acc[key]) {
        acc[key] = [];
    }
    acc[key].push(value);
    return acc;
}, {});

console.log(grouped);
実装例2(IT実務での例)
処理内容
権限集合の包含関係を確認する
viewer、editor、admin が持つ権限集合を比較し、ある役割の権限が別の役割に含まれているかを確認します。
👓 数学のメガネ:集合の包含 ⊆ は半順序の代表例です。「どちらが上位か」を単なる役職名ではなく、権限集合の関係として捉えられます。
Pythonでの実装例
viewer = {"read"}
editor = {"read", "write"}
admin = {"read", "write", "delete"}

print(viewer <= editor)
print(editor <= admin)
VBAでの実装例
Function IsSubset(smaller As Object, larger As Object) As Boolean
    Dim key As Variant
    For Each key In smaller.Keys
        If Not larger.Exists(key) Then Exit Function
    Next key
    IsSubset = True
End Function

Sub RoleOrderExample()
    Dim viewer As Object, editor As Object, admin As Object
    Set viewer = CreateObject("Scripting.Dictionary")
    Set editor = CreateObject("Scripting.Dictionary")
    Set admin = CreateObject("Scripting.Dictionary")

    viewer("read") = True
    editor("read") = True: editor("write") = True
    admin("read") = True: admin("write") = True: admin("delete") = True

    Debug.Print IsSubset(viewer, editor)
    Debug.Print IsSubset(editor, admin)
End Sub
JavaScriptでの実装例
function isSubset(smaller, larger) {
    return [...smaller].every(x => larger.has(x));
}

const viewer = new Set(["read"]);
const editor = new Set(["read", "write"]);
const admin = new Set(["read", "write", "delete"]);

console.log(isSubset(viewer, editor));
console.log(isSubset(editor, admin));

03. 集合と写像(定義域・終域・像)

数学として何なのか(定義式)
集合 X から集合 Y への写像を f : X → Y と表します。
X を定義域(domain)、Y を終域(codomain)といい、各 x ∈ X に対して f(x) ∈ Y を一つ対応させます。
実際に得られる値の集合 {f(x) | x ∈ X} を像(image)といいます。
写像は「入力された各要素に対して、出力を対応させる規則」です。
たとえば f(x)=x2 なら、1→1、2→4、3→9 という対応になります。
集合の要素を「選ぶ/選ばない」の0/1で表せば、各部分集合を0/1列として表現することもできます。
n個の要素には2n個の部分集合があるため、集合論がそのまま全探索の構造につながります。
直感的にはどういう構造なのか
集合は「対象をひとまとめにして扱う」ための数学的な単位です。
写像は、その集合の要素を別の集合の要素へ一つずつ対応させる変換規則です。
そのため、写像は「入力データの一つ一つに同じルールを適用する」というプログラムの処理とよく似ています。
また、部分集合は各要素について0か1を持つ組として表せます。
3要素なら 23=8 通りとなり、「集合の数え上げ」が「探索する組合せの数」に直結します。
IT(コード)ではどこに現れるのか
APIのリクエストパラメータ検証における入力値の型・範囲チェック(ドメインの定義)や、関数型プログラミングにおけるコレクションの変形処理(map処理)などに広く現れます。
これを知ると何が違って見えるのか(「数学のメガネ」として)
関数を単なる「場当たり的な処理のまとまり」ではなく、「定義域の各要素を一定の規則で出力側の値へ対応させる写像」として捉えられるようになります。
さらに、集合の要素を0/1で表せば、その部分集合をビットマスクとして列挙できることも見えてきます。
3要素なら23 = 8通りという「集合の大きさ」が、そのまま全探索の回数になります。
実装例1
処理内容
写像(map)による要素変換
集合の各要素に同じ変換規則を適用し、入力集合から出力集合を得ます。
Pythonでの実装例
numbers = [1, 2, 3]
squared = list(map(lambda x: x ** 2, numbers))
print(squared)
VBAでの実装例
Sub MapExample()
    Dim arr(2) As Long, i As Long
    arr(0) = 1: arr(1) = 2: arr(2) = 3
    For i = LBound(arr) To UBound(arr)
        arr(i) = arr(i) * arr(i)
    Next i
    MsgBox arr(2)
End Sub
JavaScriptでの実装例
const numbers = [1, 2, 3];
const squared = numbers.map(x => x ** 2);
console.log(squared);
実装例2
処理内容
ビット全探索(ビットマスクによる部分集合列挙)
集合の各要素を「選ぶ/選ばない」の0/1で表し、ビットマスクを変化させて部分集合をすべて列挙します。
Pythonでの実装例
items = ["A", "B", "C"]

for mask in range(1 << len(items)):
    subset = [
        items[i]
        for i in range(len(items))
        if mask & (1 << i)
    ]
    print(subset)
VBAでの実装例
Sub BitSearchExample()
    Dim items As Variant
    Dim mask As Long, i As Long
    Dim subset As String

    items = Array("A", "B", "C")

    For mask = 0 To (2 ^ (UBound(items) + 1)) - 1
        subset = ""

        For i = 0 To UBound(items)
            If (mask And CLng(2 ^ i)) <> 0 Then
                subset = subset & items(i)
            End If
        Next i

        Debug.Print subset
    Next mask
End Sub
JavaScriptでの実装例
const items = ["A", "B", "C"];

for (let mask = 0; mask < (1 << items.length); mask++) {
    const subset = [];

    for (let i = 0; i < items.length; i++) {
        if (mask & (1 << i)) {
            subset.push(items[i]);
        }
    }

    console.log(subset);
}
実装例3(IT実務での例)
処理内容
APIレスポンスを画面表示用データへ変換する
APIから受け取ったユーザーデータを、画面で使う displayName と status を持つデータへ変換します。
👓 数学のメガネ:入力集合の各要素に同じ規則を適用し、別の表現へ写す処理は「写像」として見ることができます。
Pythonでの実装例
users = [
    {"first": "Taro", "last": "Yamada", "active": True},
    {"first": "Hanako", "last": "Sato", "active": False},
]

view_models = [
    {
        "displayName": f'{u["last"]} {u["first"]}',
        "status": "有効" if u["active"] else "停止",
    }
    for u in users
]

print(view_models)
VBAでの実装例
Sub ApiMappingExample()
    Dim firstName As Variant
    Dim lastName As Variant
    Dim active As Variant
    Dim i As Long

    firstName = Array("Taro", "Hanako")
    lastName = Array("Yamada", "Sato")
    active = Array(True, False)

    For i = 0 To 1
        Debug.Print lastName(i) & " " & firstName(i), _
                    IIf(active(i), "有効", "停止")
    Next i
End Sub
JavaScriptでの実装例
const users = [
    { first: "Taro", last: "Yamada", active: true },
    { first: "Hanako", last: "Sato", active: false }
];

const viewModels = users.map(u => ({
    displayName: `${u.last} ${u.first}`,
    status: u.active ? "有効" : "停止"
}));

console.log(viewModels);
実装例4(IT実務での例)
処理内容
権限フラグをビットマスクで管理する
READ、WRITE、DELETE などの権限を1ビットずつ割り当て、複数の権限を1つの整数で表します。
AND は積集合、OR は和集合、XOR は一方だけに含まれる要素からなる対称差として見ることができます。
👓 数学のメガネ:ビットフラグの操作は、0と1の技巧ではなく、「どの権限を集合に含めるか」という集合演算として捉えられます。
Pythonでの実装例
READ = 0b0001
WRITE = 0b0010
DELETE = 0b0100

permission = READ | WRITE

print(bool(permission & WRITE))
print(bool(permission & DELETE))

permission |= DELETE
print(bool(permission & DELETE))
VBAでの実装例
Sub PermissionBitMaskExample()
    Const READ As Long = 1
    Const WRITE As Long = 2
    Const DELETE As Long = 4
    Dim permission As Long

    permission = READ Or WRITE

    Debug.Print (permission And WRITE) <> 0
    Debug.Print (permission And DELETE) <> 0

    permission = permission Or DELETE
    Debug.Print (permission And DELETE) <> 0
End Sub
JavaScriptでの実装例
const READ = 0b0001;
const WRITE = 0b0010;
const DELETE = 0b0100;

let permission = READ | WRITE;

console.log((permission & WRITE) !== 0);
console.log((permission & DELETE) !== 0);

permission |= DELETE;
console.log((permission & DELETE) !== 0);

04. グラフ理論(ノードとエッジ)

数学として何なのか(定義式)
グラフ G を、頂点(vertex)の集合 V と辺(edge)の集合 E によって G=(V,E) と表します。
辺は2つの頂点の間の接続関係を表し、頂点 u から v へ辺があれば、u と v が隣接していると考えます。
頂点と辺の向きを区別しないものを無向グラフ、向きを持たせたものを有向グラフといいます。
頂点をたどる経路(path)や、ある頂点から別の頂点へ到達できるかどうかなども、グラフ上の性質として表現できます。
つまり、グラフ理論は「対象」と「対象同士の接続」を数学的に扱う理論です。
直感的にはどういう構造なのか
グラフは、「点」と「点を結ぶ線」だけで、複雑なつながりを表せます。
道路網なら点が交差点、線が道路です。
システムなら点がサービス、線が呼び出し関係になります。
重要なのは、個々の対象そのものよりも「何と何がつながっているか」を扱えることです。
そのため、探索、経路、依存関係などを共通した構造として考えられます。
IT(コード)ではどこに現れるのか
マイクロサービス間の呼び出し依存関係の可視化、Webアプリケーションのルーティング定義、ビルドツールにおけるパッケージ間の依存解決処理などに現れます。
また、隣接するノードをたどるDFS(深さ優先探索)のように、グラフそのものが探索アルゴリズムの入力構造になります。
これを知ると何が違って見えるのか(「数学のメガネ」として)
システム間の接続や依存関係の多くを、グラフとして表現し、経路・到達可能性・依存関係などの問題として捉えられるようになります。
複雑なネットワーク構造を整理し、ボトルネックや分離すべき箇所を検討するための判断材料になります。
実装例1
処理内容
深さ優先探索(DFS)
グラフの頂点を、ある頂点から隣接する頂点へ順にたどりながら深さ優先探索を行います。
Pythonでの実装例
graph = {
    "A": ["B", "C"],
    "B": ["D"],
    "C": ["D"],
    "D": []
}

def dfs(node, visited):
    if node in visited:
        return

    visited.add(node)
    print(node)

    for next_node in graph[node]:
        dfs(next_node, visited)

dfs("A", set())
VBAでの実装例
Sub DFSExample()
    Dim graph As Object
    Dim visited As Object

    Set graph = CreateObject("Scripting.Dictionary")
    Set visited = CreateObject("Scripting.Dictionary")

    graph.Add "A", Array("B", "C")
    graph.Add "B", Array("D")
    graph.Add "C", Array("D")
    graph.Add "D", Array()

    DFS "A", graph, visited
End Sub

Sub DFS(node As String, graph As Object, visited As Object)
    Dim nextNode As Variant

    If visited.Exists(node) Then Exit Sub

    visited.Add node, True
    Debug.Print node

    For Each nextNode In graph(node)
        DFS CStr(nextNode), graph, visited
    Next nextNode
End Sub
JavaScriptでの実装例
const graph = {
    A: ["B", "C"],
    B: ["D"],
    C: ["D"],
    D: []
};

function dfs(node, visited) {
    if (visited.has(node)) return;

    visited.add(node);
    console.log(node);

    for (const nextNode of graph[node]) {
        dfs(nextNode, visited);
    }
}

dfs("A", new Set());
実装例2(IT実務での例)
処理内容
障害の影響範囲をサービス依存関係から調べる
database が停止したとき、直接または間接的に影響を受けるサービスを依存グラフからたどります。
👓 数学のメガネ:サービスをノード、依存関係をエッジと見れば、障害影響調査はグラフ上の到達可能性の問題になります。
Pythonでの実装例
dependents = {
    "database": ["order-api", "billing-api"],
    "order-api": ["web"],
    "billing-api": ["web"],
    "web": [],
}

def affected(service, seen=None):
    seen = seen or set()
    for next_service in dependents[service]:
        if next_service not in seen:
            seen.add(next_service)
            affected(next_service, seen)
    return seen

print(affected("database"))
VBAでの実装例
Sub ImpactExample()
    Dim graph As Object, seen As Object
    Set graph = CreateObject("Scripting.Dictionary")
    Set seen = CreateObject("Scripting.Dictionary")

    graph.Add "database", Array("order-api", "billing-api")
    graph.Add "order-api", Array("web")
    graph.Add "billing-api", Array("web")
    graph.Add "web", Array()

    TraceImpact "database", graph, seen
End Sub

Sub TraceImpact(service As String, graph As Object, seen As Object)
    Dim nextService As Variant
    For Each nextService In graph(service)
        If Not seen.Exists(nextService) Then
            seen.Add nextService, True
            Debug.Print nextService
            TraceImpact CStr(nextService), graph, seen
        End If
    Next nextService
End Sub
JavaScriptでの実装例
const dependents = {
    "database": ["order-api", "billing-api"],
    "order-api": ["web"],
    "billing-api": ["web"],
    "web": []
};

function affected(service, seen = new Set()) {
    for (const nextService of dependents[service]) {
        if (!seen.has(nextService)) {
            seen.add(nextService);
            affected(nextService, seen);
        }
    }
    return seen;
}

console.log([...affected("database")]);

05. 木構造とハッシュ

数学として何なのか(定義式)
木は、連結で閉路を持たないグラフです。
有限の木 T=(V,E) では、頂点数を |V| とすると辺数は |E|=|V|-1 になります。
階層構造として見ると、根から各ノードへ至る経路が一意に定まるという性質を持ちます。
一方、ハッシュでは、キーの集合 K から配列の添字などの有限集合 {0,1,...,m-1} への写像 h : K → {0,1,...,m-1} を考えます。
異なるキーが同じ値に写る衝突(collision)が起こり得るため、その扱いも重要になります。
木とハッシュはどちらも、データを効率よく配置・探索するための構造として、集合や関係の数学からつながっています。
直感的にはどういう構造なのか
木は、「一つの根から枝分かれしていく階層」と考えるとわかりやすい構造です。
途中で輪にならないため、親子関係をたどる経路が整理されています。
ハッシュは、「キーを計算して、保存場所を決める」という発想です。
キーそのものを順番に探すのではなく、ハッシュ値を手掛かりに場所を絞り込みます。
同じ「探す」という処理でも、線形に並べる、階層化する、ハッシュ値で場所を決めるという構造の違いが、探索方法や計算量の違いになります。
IT(コード)ではどこに現れるのか
HTML/XMLのDOMツリー操作、JSONデータの階層パース処理、そして高速なキーバリュー検索を実現するハッシュマップ(辞書型)の内部実装などに現れます。
これを知ると何が違って見えるのか(「数学のメガネ」として)
データの配置が「線形(リスト)」か「階層(ツリー)」か「散らばり(ハッシュ)」かによって、探索・更新の方法や計算コストが変わることを理解しやすくなります。
用途に応じたデータ構造を選ぶための判断材料になります。
実装例1
処理内容
辞書・Mapによるキー検索
キーを使って値を検索し、キーと値の対応を利用した高速な参照を行います。
Pythonでの実装例
user_dict = {"usr_001": "Alice"}
print(user_dict.get("usr_001"))
VBAでの実装例
Sub HashExample()
    Dim dict As Object
    Set dict = CreateObject("Scripting.Dictionary")
    dict.Add "usr_001", "Alice"
    MsgBox dict("usr_001")
End Sub
JavaScriptでの実装例
const userMap = new Map();
userMap.set("usr_001", "Alice");
console.log(userMap.get("usr_001"));
実装例2
処理内容
二分木の実装と走査
ノードが子ノードを参照する形で木構造を表現し、根から各ノードをたどります。ここでは深さ優先の前順走査(Preorder Traversal)を行います。
Pythonでの実装例
tree = {
    "value": "A",
    "left": {"value": "B", "left": None, "right": None},
    "right": {"value": "C", "left": None, "right": None}
}

def preorder(node):
    if node is None:
        return
    print(node["value"])
    preorder(node["left"])
    preorder(node["right"])

preorder(tree)
VBAでの実装例
Sub TreeExample()
    Dim value As Variant
    Dim left As Variant
    Dim right As Variant

    value = Array("A", "B", "C")
    left = Array(1, -1, -1)
    right = Array(2, -1, -1)

    Preorder value, left, right, 0
End Sub

Sub Preorder(value As Variant, left As Variant, right As Variant, index As Long)
    If index < 0 Then Exit Sub

    Debug.Print value(index)
    Preorder value, left, right, left(index)
    Preorder value, left, right, right(index)
End Sub
JavaScriptでの実装例
const tree = {
    value: "A",
    left: { value: "B", left: null, right: null },
    right: { value: "C", left: null, right: null }
};

function preorder(node) {
    if (node === null) return;
    console.log(node.value);
    preorder(node.left);
    preorder(node.right);
}

preorder(tree);
実装例3(IT実務での例)
処理内容
組織ツリーから所属メンバーをたどる
部門の下にチームがぶら下がる組織階層を、根から再帰的にたどって表示します。
👓 数学のメガネ:組織図やメニュー、フォルダ構造は、実務では「木」として現れます。再帰処理はその階層構造を素直にたどる方法です。
Pythonでの実装例
organization = {
    "name": "開発部",
    "children": [
        {"name": "基盤チーム", "children": []},
        {"name": "業務チーム", "children": []},
    ],
}

def walk(node, depth=0):
    print("  " * depth + node["name"])
    for child in node["children"]:
        walk(child, depth + 1)

walk(organization)
VBAでの実装例
Sub OrganizationTreeExample()
    Dim names As Variant
    Dim parent As Variant
    Dim i As Long

    names = Array("開発部", "基盤チーム", "業務チーム")
    parent = Array(-1, 0, 0)

    PrintChildren names, parent, -1, 0
End Sub

Sub PrintChildren( _
    names As Variant, _
    parent As Variant, _
    parentIndex As Long, _
    depth As Long)

    Dim i As Long

    For i = LBound(names) To UBound(names)
        If parent(i) = parentIndex Then
            Debug.Print Space(depth * 2) & names(i)
            PrintChildren names, parent, i, depth + 1
        End If
    Next i
End Sub
JavaScriptでの実装例
const organization = {
    name: "開発部",
    children: [
        { name: "基盤チーム", children: [] },
        { name: "業務チーム", children: [] }
    ]
};

function walk(node, depth = 0) {
    console.log("  ".repeat(depth) + node.name);
    node.children.forEach(child => walk(child, depth + 1));
}

walk(organization);

06. 代数的構造と合同算術

数学として何なのか(定義式)
集合 G と、その上で定義された二項演算 · を考えます。結合律 (a·b)·c=a·(b·c)、単位元 e の存在 e·a=a·e=a、逆元 a-1 の存在 a·a-1=a-1·a=e などを満たすものを群 (G,·) といいます。
環や体は、加法と乗法など複数の演算について、さらに条件を加えて定義した代数的構造です。
つまり「どんな計算ができるか」だけでなく、「その計算がどのような法則に従うか」を数学的に扱います。
合同算術では、整数 a と b が正の整数 m に対して同じ余りを持つとき、a ≡ b (mod m) と表します。
これは a-b が m の倍数であること、すなわち m | (a-b) と同値です。
剰余演算では a mod m のように余りを取り出し、暗号などでは大きな整数のべき乗を法 m で計算する「べき乗剰余」も重要になります。
直感的にはどういう構造なのか
群・環・体では、「計算の結果」よりも、その計算がどのような法則に従うかに注目します。
一方、合同算術は整数をそのまま並べるのではなく、「mで割った余りが同じもの」を同じ仲間として扱う見方です。
たとえば時計では、12時の次が13時ではなく1時になります。
これは12を法とする計算として考えることができ、一定の範囲を越えると最初に戻る循環構造を数学的に表せます。
この見方を持つと、単純な剰余演算が、ハッシュ、循環処理、チェックサム、暗号などに共通して現れる理由が見えてきます。
IT(コード)ではどこに現れるのか
ハッシュ値をテーブル位置へ変換する処理、リングバッファや周期処理、チェックサム、暗号アルゴリズムなどに剰余演算が現れます。
特に公開鍵暗号では、巨大な整数に対するべき乗を法の下で計算する「べき乗剰余」が重要な基本操作になります。
XOR(排他的論理和)のようなビット演算も、演算そのものが持つ性質を利用することで、可逆な処理やビット状態の操作に応用できます。
たとえばXORには、同じ値同士では0になる(A XOR A = 0)、0とのXORでは元の値が残る(A XOR 0 = A)という性質があり、これを利用すると一時変数を使わずに2つの整数値を交換することもできます。
ただし、XORによる値交換は性質を理解する例としては有名ですが、実務では可読性の高い通常の交換方法を使うのが一般的です。
これを知ると何が違って見えるのか(「数学のメガネ」として)
「整数を計算している」のではなく、「ある法則を満たす演算体系の中で計算している」と見ることができます。
さらに、mod を単なる余りを求める演算ではなく、値を一定の周期で折り返す仕組みとして見ると、ハッシュや暗号などに現れる処理を共通する数学的構造として捉えられるようになります。
実装例1
処理内容
剰余演算(モジュラー演算)
整数を一定の法で割った余りを求め、周期的に値を扱う計算を確認します。
Pythonでの実装例
values = [10, 11, 12, 13, 24]
modulus = 12

print([value % modulus for value in values])
VBAでの実装例
Sub ModuloExample()
    Dim values As Variant
    Dim i As Long
    Dim modulus As Long

    values = Array(10, 11, 12, 13, 24)
    modulus = 12

    For i = LBound(values) To UBound(values)
        Debug.Print values(i) Mod modulus
    Next i
End Sub
JavaScriptでの実装例
const values = [10, 11, 12, 13, 24];
const modulus = 12;

console.log(values.map(value => value % modulus));
実装例2
処理内容
べき乗剰余(modular exponentiation)
ab をそのまま計算せず、法 m における余りを求めます。大きな整数を扱う暗号アルゴリズムで使われる基本的な処理です。
Pythonでの実装例
base = 7
exponent = 13
modulus = 10

print(pow(base, exponent, modulus))
VBAでの実装例
Sub ModularPowerExample()
    Dim base As Long, exponent As Long, modulus As Long
    Dim result As Long

    base = 7
    exponent = 13
    modulus = 10
    result = 1
    base = base Mod modulus

    Do While exponent > 0
        If exponent Mod 2 = 1 Then
            result = (result * base) Mod modulus
        End If
        base = (base * base) Mod modulus
        exponent = exponent \ 2
    Loop

    Debug.Print result
End Sub

※ 繰り返し二乗法による実装です。ただし、VBAの Long には扱える整数の範囲に制限があるため、暗号で扱うような巨大整数をそのまま計算する用途には使用できません。

JavaScriptでの実装例
let base = 7n;
let exponent = 13n;
const modulus = 10n;
let result = 1n;

while (exponent > 0n) {
    if (exponent % 2n === 1n) {
        result = (result * base) % modulus;
    }
    base = (base * base) % modulus;
    exponent = exponent / 2n;
}

console.log(result.toString());

※ JavaScriptでは、整数リテラルの末尾に n を付けると BigInt になります。通常の Number では正確に扱える整数の範囲に限界があるため、大きな整数を扱う場合に使用します。ここでは、大きな整数を扱う場面を想定して BigInt を使用しています。BigInt と Number は混在させて演算できません。

実装例3(IT実務での例)
処理内容
当番を周期的にローテーションする
担当者リストを順番に巡回し、日数が人数を超えても先頭へ戻る当番表を作ります。
👓 数学のメガネ:「最後まで行ったら先頭に戻す」という処理は、人数を法とする合同算術として書けます。
Pythonでの実装例
engineers = ["Aki", "Mika", "Ken"]

for day in range(7):
    person = engineers[day % len(engineers)]
    print(day + 1, person)
VBAでの実装例
Sub RotationExample()
    Dim engineers As Variant
    Dim day As Long, index As Long

    engineers = Array("Aki", "Mika", "Ken")

    For day = 0 To 6
        index = day Mod (UBound(engineers) + 1)
        Debug.Print day + 1, engineers(index)
    Next day
End Sub
JavaScriptでの実装例
const engineers = ["Aki", "Mika", "Ken"];

for (let day = 0; day < 7; day++) {
    const person = engineers[day % engineers.length];
    console.log(day + 1, person);
}
ここからは、整数の2進表現とビット演算の性質を利用した、有名なプログラミングテクニックも見ておきます。

実装例4(有名なビットテクニック)
処理内容
2のべき乗をビット演算で判定する
2のべき乗は、2進数で表すと1になっているビットが1つだけです。
たとえば 8 は 1000、7 は 0111 なので、8 AND 7 = 0 になります。
この性質から、正の整数 n が2のべき乗かどうかを n & (n - 1) で判定できます。
👓 数学のメガネ:一見すると呪文のようなビット演算も、2進表現の構造を見ると「なぜ動くのか」を説明できます。
Pythonでの実装例
def is_power_of_two(n):
    return n > 0 and (n & (n - 1)) == 0

print(is_power_of_two(8))
print(is_power_of_two(10))
VBAでの実装例
Function IsPowerOfTwo(n As Long) As Boolean
    If n <= 0 Then
        IsPowerOfTwo = False
    Else
        IsPowerOfTwo = (n And (n - 1)) = 0
    End If
End Function

Sub PowerOfTwoExample()
    Debug.Print IsPowerOfTwo(8)
    Debug.Print IsPowerOfTwo(10)
End Sub
JavaScriptでの実装例
function isPowerOfTwo(n) {
    return n > 0n && (n & (n - 1n)) === 0n;
}

console.log(isPowerOfTwo(8n));
console.log(isPowerOfTwo(10n));
実装例5(ビット列の差分)
処理内容
XORとpopcountでハミング距離を求める
2つのビット列をXORすると、異なる位置のビットだけが1になります。
その1の個数(popcount)を数えれば、2つのビット列が何箇所異なるかを表す「ハミング距離」になります。
誤り検出、ビット列の比較、ハッシュや画像などの類似度判定につながる考え方です。
👓 数学のメガネ:XORは値交換の裏技だけではなく、「異なる部分を取り出す演算」として見ると、距離の計算へつながります。
Pythonでの実装例
a = 0b101101
b = 0b100001

distance = (a ^ b).bit_count()
print(distance)
VBAでの実装例
Function HammingDistance(a As Long, b As Long) As Long
    Dim x As Long
    x = a Xor b

    Do While x <> 0
        x = x And (x - 1)
        HammingDistance = HammingDistance + 1
    Loop
End Function

Sub HammingExample()
    Debug.Print HammingDistance(45, 33)
End Sub
JavaScriptでの実装例
function bitCount(n) {
    let count = 0;
    while (n !== 0) {
        n &= n - 1;
        count++;
    }
    return count;
}

const a = 0b101101;
const b = 0b100001;

console.log(bitCount(a ^ b));

※このJavaScript例は、説明を簡潔にするため非負の32ビット整数を対象としています。



第2章:繰り返しと近似を見る数学(07~10)

プログラムの処理は、入力を受け取り、繰り返し計算しながら状態を変化させ、最終的な結果へ近づいていきます。
ここでは、その「繰り返し」「近似」「増え方」を数学的に捉えるためのメガネを揃えます。

数列や漸化式は、前の値から次の値がどのように決まるかを表します。
極限や無限級数は、繰り返しを続けた先で何に近づくのかを考えます。
浮動小数点数の誤差では、数学上の実数を有限の情報で近似すると何が起こるのかを捉えます。
そして計算量では、入力の大きさが変わったときに処理量がどのように増えるのかを捉えます。
「処理を何回繰り返すのか」だけでなく、「繰り返すと何がどう変化するのか」「入力が増えると計算量がどう増えるのか」という視点を持つことが、この章のポイントです。

こうした考え方は、アルゴリズム解析や数値計算など、計算の過程・精度・効率を扱う分野につながっています。

07. 数列と漸化式

数学として何なのか(定義式)
数列は、自然数 n に対して数 an を対応させたものとして考えられます。
漸化式は、前の項から次の項を決める関係式です。
たとえばフィボナッチ数列は a0=0、a1=1 を初期条件として、an=an-1+an-2 と表されます。
つまり漸化式では、n番目の値を単独で考えるのではなく、「現在の値が、それ以前の値からどのように生まれるか」という変化の規則を定義します。
また、差分作用素を Δan=an+1-an と定義すると、隣り合う値の変化量を取り出せます。
これは連続量を扱う微分に対する、離散的な変化の見方につながります。
直感的にはどういう構造なのか
数列は「値が順番に並んでいるもの」、漸化式は「次の値を前の値から作るルール」と考えるとわかりやすくなります。
差分は、その並びの中から「一つ進んだときにどれだけ変わったか」を取り出す操作です。
たとえば 10, 13, 18 なら、差分は 3, 5 になります。
こうして見ると、ループによる繰り返し計算は「前の状態から次の状態を生成する」という数列・漸化式の構造として捉えられます。
IT(コード)ではどこに現れるのか
複雑な木構造の走査を行う再帰関数、キャッシュを活用して計算量を削減する動的計画法(DP)、金融システムにおける複利計算のシミュレーションなどに現れます。
また、離散的なデータの変化を取り出す差分「Δan = an+1 - an」も、数列の考え方をそのままプログラムにしたものと見ることができます。
これを知ると何が違って見えるのか(「数学のメガネ」として)
ループ処理や再帰アルゴリズムを書く際、「直前の状態がどのように次へ伝播していくか」という漸化式の構造を意識できるようになります。
再帰や反復処理を状態遷移の規則として捉えることで、終了条件や状態の変化を整理しやすくなります。
実装例1
処理内容
再帰によるフィボナッチ数の計算
漸化式に従って、第n項のフィボナッチ数を再帰的に計算します。
Pythonでの実装例
def fib(n):
    if n < 2: return n
    return fib(n - 1) + fib(n - 2)
VBAでの実装例
Function Fib(n As Long) As Long
    If n < 2 Then
        Fib = n
    Else
        Fib = Fib(n - 1) + Fib(n - 2)
    End If
End Function
JavaScriptでの実装例
function fib(n) {
    if (n < 2) return n;
    return fib(n - 1) + fib(n - 2);
}

console.log(fib(10));
実装例2
処理内容
差分(差分作用素)
離散データの隣り合う値の差を求め、数列の変化量を取り出します。
Pythonでの実装例
data = [10, 13, 18, 20, 25]

diff = [
    data[i + 1] - data[i]
    for i in range(len(data) - 1)
]

print(diff)
VBAでの実装例
Sub DifferenceExample()
    Dim data As Variant
    Dim diff() As Long
    Dim i As Long

    data = Array(10, 13, 18, 20, 25)
    ReDim diff(0 To UBound(data) - 1)

    For i = 0 To UBound(diff)
        diff(i) = data(i + 1) - data(i)
    Next i

    For i = 0 To UBound(diff)
        Debug.Print diff(i)
    Next i
End Sub
JavaScriptでの実装例
const data = [10, 13, 18, 20, 25];

const diff = [];
for (let i = 0; i < data.length - 1; i++) {
    diff.push(data[i + 1] - data[i]);
}

console.log(diff);
実装例3(IT実務での例)
処理内容
在庫残数を日々の入出庫から更新する
現在庫に、その日の入庫・出庫による増減を反映しながら次の日の在庫を順番に求めます。
👓 数学のメガネ:「次の在庫 = 現在の在庫 + 当日の増減」という業務処理は、現在の状態から次の状態を決める漸化式そのものです。
Pythonでの実装例
stock = 100
changes = [-10, -20, 50, -15]

for change in changes:
    stock = stock + change
    print(stock)
VBAでの実装例
Sub StockTransitionExample()
    Dim stock As Long
    Dim changes As Variant
    Dim i As Long

    stock = 100
    changes = Array(-10, -20, 50, -15)

    For i = LBound(changes) To UBound(changes)
        stock = stock + changes(i)
        Debug.Print stock
    Next i
End Sub
JavaScriptでの実装例
let stock = 100;
const changes = [-10, -20, 50, -15];

for (const change of changes) {
    stock = stock + change;
    console.log(stock);
}
実装例4(IT実務での例)
処理内容
API再試行の指数バックオフ
通信エラーなどで処理を再試行するとき、1秒、2秒、4秒、8秒……のように待機時間を増やします。
待機時間 an は、an+1 = 2an という漸化式で表せる等比数列です。
👓 数学のメガネ:wait *= 2 という実務コードも、「前の値から次の値を決める」という漸化式そのものです。
Pythonでの実装例
wait = 1

for retry in range(5):
    print(retry + 1, wait)
    wait *= 2
VBAでの実装例
Sub ExponentialBackoffExample()
    Dim wait As Long
    Dim retry As Long

    wait = 1

    For retry = 1 To 5
        Debug.Print retry, wait
        wait = wait * 2
    Next retry
End Sub
JavaScriptでの実装例
let wait = 1;

for (let retry = 1; retry <= 5; retry++) {
    console.log(retry, wait);
    wait *= 2;
}

※実際の指数バックオフでは、待機時間の上限を設けたり、同時再試行の集中を避けるためにランダムな揺らぎ(jitter)を加えたりすることがあります。


08. 極限と無限級数

数学として何なのか(定義式)
数列 an の項を無限に足し合わせるものを無限級数といい、∑n=0∞an と表します。
部分和 SN=∑n=0Nan を考え、N→∞ のとき SN がある値に近づくなら、その級数は収束するといいます。
たとえば等比級数 1 + 1/2 + 1/4 + ... は、部分和が 2 に近づき、∑n=0∞(1/2)n=2 となります。
コンピューターでは無限回の計算はできないため、有限個の項による部分和を計算して、無限の対象を有限の計算で近似します。
直感的にはどういう構造なのか
「無限」はコンピューターでそのまま計算するものではありません。
最初の何項まで計算したら、求めたい値にどれくらい近づくのかを考えます。
つまり、無限級数は「永遠に繰り返す計算」というより、「繰り返しを増やすと結果がどこへ近づくか」を考える数学です。
この視点を持つと、数値計算や近似計算で「何回計算すれば十分なのか」という問題も、極限や収束の問題として見えてきます。
IT(コード)ではどこに現れるのか
数値シミュレーションにおける誤差の収束判定、機械学習の最適化計算におけるイテレーション終了条件、有限精度の浮動小数点演算における限界値の評価などに現れます。
また、無限級数を有限回だけ計算して近似する処理にも、極限という考え方が直接現れます。
これを知ると何が違って見えるのか(「数学のメガネ」として)
「無限を直接計算することはできなくても、有限回の計算でどこまで近づけるか」という発想が身につきます。
「値が近づく」と「値が等しくなる」を区別できるようになり、数値計算における収束判定や近似計算を、単なるループではなく極限の考え方として捉えられるようになります。
実装例1
処理内容
無限級数の有限近似
各項を半分にしながら30項まで加算し、無限級数 1 + 1/2 + 1/4 + … の値に近づけます。
Pythonでの実装例
total = 0.0
term = 1.0

for _ in range(30):
    total += term
    term /= 2

print(total)
VBAでの実装例
Sub InfiniteSeriesExample()
    Dim total As Double
    Dim term As Double
    Dim i As Long

    total = 0#
    term = 1#

    For i = 1 To 30
        total = total + term
        term = term / 2
    Next i

    Debug.Print total
End Sub
JavaScriptでの実装例
let total = 0;
let term = 1;

for (let i = 0; i < 30; i++) {
    total += term;
    term /= 2;
}

console.log(total);
実装例2(IT実務での例)
処理内容
監視値の推定を変化が小さくなるまで更新する
レスポンスタイムの推定値を新しい観測値へ少しずつ近づけ、更新幅が十分小さくなったら反復を終了します。
👓 数学のメガネ:実務の反復計算でも「何回回すか」だけでなく「値がどこへ近づき、いつ十分に近づいたとみなすか」という収束の考え方が使われます。
Pythonでの実装例
estimate = 1000.0
target = 250.0
epsilon = 0.1

while True:
    next_estimate = (estimate + target) / 2
    if abs(next_estimate - estimate) < epsilon:
        estimate = next_estimate
        break
    estimate = next_estimate

print(estimate)
VBAでの実装例
Sub ConvergenceExample()
    Dim estimate As Double, target As Double
    Dim nextEstimate As Double, epsilon As Double

    estimate = 1000#
    target = 250#
    epsilon = 0.1

    Do
        nextEstimate = (estimate + target) / 2
        If Abs(nextEstimate - estimate) < epsilon Then
            estimate = nextEstimate
            Exit Do
        End If
        estimate = nextEstimate
    Loop

    Debug.Print estimate
End Sub
JavaScriptでの実装例
let estimate = 1000.0;
const target = 250.0;
const epsilon = 0.1;

while (true) {
    const nextEstimate = (estimate + target) / 2;
    if (Math.abs(nextEstimate - estimate) < epsilon) {
        estimate = nextEstimate;
        break;
    }
    estimate = nextEstimate;
}

console.log(estimate);

09. 浮動小数点数の誤差

数学として何なのか(定義式)
数学では、実数を連続した数として扱います。
しかしコンピューターは有限個のビットしか使えないため、すべての実数を正確に表現できるわけではありません。
浮動小数点数では、数値を有限精度で近似して表現するため、表現誤差や丸め誤差が生じます。
たとえば10進数の 0.1 は、2進数では有限桁で正確に表現できません。
そのため、プログラム内部では0.1を「0.1そのもの」ではなく、近い表現可能な値として保持することがあります。
この誤差が計算の途中で積み重なると、期待した値との小さな差として現れます。
直感的にはどういう構造なのか
実数を無限に細かい目盛りの定規だとすると、コンピューター上の浮動小数点数は、その定規から選んだ有限個の目盛りだと考えられます。
表現できる数と数の間にある値を扱うときは、近い値へ丸める必要があります。
つまり「数学上では等しい」「コンピューター上では近い値として表現される」という違いがあります。
これはプログラミング言語の気まぐれではなく、有限の情報量で数を表現するというコンピューターの仕組みから生じる問題です。
IT(コード)ではどこに現れるのか
浮動小数点型による計算、科学技術計算、統計処理、グラフィックスなど、数値を近似的に扱う多くの処理に現れます。
金額のように正確な10進表現が重要な値では、整数化や十進型など、用途に応じた数値表現を選ぶ必要があります。
これを知ると何が違って見えるのか(「数学のメガネ」として)
「計算した結果が違う」のではなく、「入力した数値そのものがコンピューター上では近似値として表現されている」と考えられるようになります。
完全一致ではなく許容誤差で比較する、丸める場所を設計する、用途に応じて数値型を選択するといった判断を、数学的な理由を持って行えるようになります。
実装例1
処理内容
浮動小数点誤差の確認
0.1 と 0.2 を加算し、浮動小数点数では10進数の値を完全には表現できない場合があることを確認します。
Pythonでの実装例
result = 0.1 + 0.2
print(result)
print(result == 0.3)
VBAでの実装例
Sub FloatingPointErrorExample()
    Dim result As Double

    result = 0.1 + 0.2
    Debug.Print result
    Debug.Print result = 0.3
End Sub
JavaScriptでの実装例
const result = 0.1 + 0.2;
console.log(result);
console.log(result === 0.3);
実装例2
処理内容
許容誤差による浮動小数点比較
完全一致ではなく、二つの値の差が許容範囲内にあるかどうかで近似的な等価性を判定します。
Pythonでの実装例
import math

a = 0.1 + 0.2
b = 0.3

epsilon = 1e-12
print(math.isclose(a, b, rel_tol=0.0, abs_tol=epsilon))
VBAでの実装例
Sub ApproximateCompareExample()
    Dim a As Double, b As Double
    Dim epsilon As Double

    a = 0.1 + 0.2
    b = 0.3
    epsilon = 0.000000000001

    Debug.Print Abs(a - b) <= epsilon
End Sub
JavaScriptでの実装例
const a = 0.1 + 0.2;
const b = 0.3;
const epsilon = 1e-12;

console.log(Math.abs(a - b) <= epsilon);
実装例3(IT実務での例)
処理内容
数値計算のテストで期待値と近似比較する
計算結果を単純な完全一致で比較せず、許容誤差以内なら同じ結果として扱うテストを行います。
👓 数学のメガネ:浮動小数点を使う処理では、「等しいか」ではなく「必要な精度の範囲で十分近いか」という比較が実務でも重要です。
Pythonでの実装例
actual = (0.1 + 0.2) * 100
expected = 30.0
epsilon = 1e-10

assert abs(actual - expected) <= epsilon
print("OK")
VBAでの実装例
Sub NumericTestExample()
    Dim actual As Double, expected As Double
    Dim epsilon As Double

    actual = (0.1 + 0.2) * 100
    expected = 30#
    epsilon = 0.0000000001

    Debug.Assert Abs(actual - expected) <= epsilon
    Debug.Print "OK"
End Sub
JavaScriptでの実装例
const actual = (0.1 + 0.2) * 100;
const expected = 30.0;
const epsilon = 1e-10;

console.assert(Math.abs(actual - expected) <= epsilon);
console.log("OK");

10. アルゴリズムの計算量(オーダー表記)

数学として何なのか(定義式)
アルゴリズムの計算量では、入力サイズ n に対して必要な計算回数がどのように増えるかを漸近的に表します。
代表的なオーダー表記が O(1)、O(log n)、O(n)、O(n log n)、O(n2) などです。
たとえば、n個のデータを一度ずつ調べる処理は O(n)、n個のデータ同士をすべて組み合わせて調べる処理は O(n2) になります。
Big O は定数倍や低次の項を無視し、入力が大きくなったときの増え方に注目します。
計算量は「今のデータで何秒かかるか」ではなく、「データが増えたときに処理量がどのように増えるか」を数学的に表す尺度です。
直感的にはどういう構造なのか
計算量は、処理時間そのものを測るものではなく、「入力が10倍になったら、計算量はどの程度増えるか」という増え方を見るものです。
O(n) と O(n2) は、少ないデータではそれほど違わなくても、nが大きくなると差が急激に広がります。
そのため、コードを見るときに「この処理は何回繰り返されるのか」だけでなく、「入力サイズに対して、その回数がどのように増えるのか」を考えることができます。
IT(コード)ではどこに現れるのか
データ件数が増加した際にシステムが耐えられるかを評価するコードレビューや、リスト内包表記とハッシュセットを組み合わせた高速なフィルタリング処理の実装などに現れます。
これを知ると何が違って見えるのか(「数学のメガネ」として)
コードを見るときに、「入力件数が増えたとき、この処理量はどのように増えるのか」という視点を持てるようになります。
二重ループや探索方法の違いが性能へ与える影響を、実測だけでなく計算量の観点から判断する材料になります。
実装例1
処理内容
ハッシュ探索と線形探索
集合を使った検索と二重ループを比較し、データ件数が増えたときの処理量の違いを確認します。
Pythonでの実装例
list_a = [1, 2, 3]
list_b = [2, 3, 4]

# 二重探索:O(n × m)
slow_result = [x for x in list_a if any(x == y for y in list_b)]

# Setを使った探索:Set作成 O(m) + 探索 O(n)(平均的)
set_b = set(list_b)
fast_result = [x for x in list_a if x in set_b]

print(slow_result)
print(fast_result)
VBAでの実装例
Sub OrderExample()
    Dim listA As Variant, listB As Variant
    Dim dict As Object
    Dim slowResult As Collection, fastResult As Collection
    Dim i As Long, j As Long

    listA = Array(1, 2, 3)
    listB = Array(2, 3, 4)
    Set slowResult = New Collection
    Set fastResult = New Collection

    ' 二重探索:O(n × m)
    For i = LBound(listA) To UBound(listA)
        For j = LBound(listB) To UBound(listB)
            If listA(i) = listB(j) Then
                slowResult.Add listA(i)
                Exit For
            End If
        Next j
    Next i

    ' Dictionaryを使った探索:作成 O(m) + 探索 O(n)(平均的)
    Set dict = CreateObject("Scripting.Dictionary")
    For j = LBound(listB) To UBound(listB)
        dict(listB(j)) = True
    Next j

    For i = LBound(listA) To UBound(listA)
        If dict.Exists(listA(i)) Then fastResult.Add listA(i)
    Next i

    For i = 1 To slowResult.Count
        Debug.Print slowResult(i)
    Next i
    For i = 1 To fastResult.Count
        Debug.Print fastResult(i)
    Next i
End Sub
JavaScriptでの実装例
const listA = [1, 2, 3];
const listB = [2, 3, 4];

// 二重探索:O(n × m)
const slowResult = listA.filter(x => listB.some(y => x === y));

// Setを使った探索:Set作成 O(m) + 探索 O(n)(平均的)
const setB = new Set(listB);
const fastResult = listA.filter(x => setB.has(x));

console.log(slowResult);
console.log(fastResult);
実装例2(IT実務での例)
処理内容
売上データの商品コードをマスタと突合する
売上明細の商品コードが商品マスタに存在するかをSet / Dictionaryで確認し、未知の商品コードだけを抽出します。
👓 数学のメガネ:大量データの突合は「各行ごとにマスタを最初から探す」のではなく、探索構造を先に作ることで計算量を大きく抑えられます。
Pythonでの実装例
master_codes = {"P001", "P002", "P003"}
sales_codes = ["P001", "P999", "P002", "P888"]

unknown = [code for code in sales_codes if code not in master_codes]
print(unknown)
VBAでの実装例
Sub MasterLookupExample()
    Dim master As Object
    Dim sales As Variant
    Dim code As Variant

    Set master = CreateObject("Scripting.Dictionary")
    master("P001") = True
    master("P002") = True
    master("P003") = True

    sales = Array("P001", "P999", "P002", "P888")

    For Each code In sales
        If Not master.Exists(code) Then Debug.Print code
    Next code
End Sub
JavaScriptでの実装例
const masterCodes = new Set(["P001", "P002", "P003"]);
const salesCodes = ["P001", "P999", "P002", "P888"];

const unknown = salesCodes.filter(code => !masterCodes.has(code));
console.log(unknown);
実装例3(IT実務での例)
処理内容
二分探索と log2 n
ソート済みデータの中央を調べ、目的の値が左右どちらにあるかによって探索範囲を半分ずつ捨てていきます。
100万件のデータでも、220 = 1,048,576 なので、およそ20回「半分にする」だけで候補を1件程度まで絞れます。
この「何回2で割れば1付近まで小さくなるか」を表しているのが log2 n であり、二分探索の計算量 O(log n) の直感につながります。
👓 数学のメガネ:O(log n) の log は単なる記号ではなく、「問題の大きさを何回半分にできるか」という回数として見ることができます。
Pythonでの実装例
data = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
target = 70
left, right = 0, len(data) - 1

while left <= right:
    mid = (left + right) // 2
    if data[mid] == target:
        print(mid)
        break
    elif data[mid] < target:
        left = mid + 1
    else:
        right = mid - 1
VBAでの実装例
Sub BinarySearchExample()
    Dim data As Variant
    Dim target As Long
    Dim left As Long, right As Long, mid As Long

    data = Array(10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
    target = 70
    left = LBound(data)
    right = UBound(data)

    Do While left <= right
        mid = (left + right) \ 2

        If data(mid) = target Then
            Debug.Print mid
            Exit Do
        ElseIf data(mid) < target Then
            left = mid + 1
        Else
            right = mid - 1
        End If
    Loop
End Sub
JavaScriptでの実装例
const data = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
const target = 70;
let left = 0;
let right = data.length - 1;

while (left <= right) {
    const mid = Math.floor((left + right) / 2);

    if (data[mid] === target) {
        console.log(mid);
        break;
    } else if (data[mid] < target) {
        left = mid + 1;
    } else {
        right = mid - 1;
    }
}


第3章:不確実性とデータを見る数学(11~16)

現実に稼働するシステムは、曖昧な入力や「不確実性」に満ちています。
観測されたデータから背後の状態を推論し、確率的モデルとして捉えます。

ここで扱う数学では、「起こり得る場合を数える」「ある事象が起こる確率を求める」「データから母集団を推定する」「情報の不確実さを測る」といった考え方を扱います。
結果が一つに決まらない現実のデータを、確率や統計によって数学的な対象として記述します。
この見方を持つと、ランダムなデータ、測定結果、検索結果、機械学習の予測などを、単なる数値の集まりではなく「確率的な構造を持つデータ」として捉えられるようになります。

こうした数学は、確率・統計を基盤として、データ分析、機械学習、情報理論など、不確実性を含むデータを扱う分野につながっています。

11. 場合の数と順列・組み合わせ

数学として何なのか(定義式)
場合の数は、条件を満たす対象が何通りあるかを数える数学です。
異なる n 個から順序を考慮して r 個を選ぶ順列は nPr=n!/(n-r)!、順序を考慮せず r 個を選ぶ組合せは nCr=n!/(r!(n-r)!) で表されます。
順列では「A,B」と「B,A」を別のものとして数えますが、組合せでは同じものとして数えます。
この「順序を区別するかどうか」が、数え上げの基本的な分岐になります。
組合せの数は、全探索で調べなければならない候補数を事前に見積もるときにも使えます。
直感的にはどういう構造なのか
「何通りあるか」を先に数えることで、問題の大きさを把握できます。
たとえば4人から2人を選ぶなら 4C2=6 通りです。
実際に6通りを列挙することもできますし、候補数だけを計算して探索が現実的かどうかを判断することもできます。
つまり、場合の数は単なる組合せ問題ではなく、「コンピューターが調べる候補の数を数学的に見積もる」ための考え方でもあります。
IT(コード)ではどこに現れるのか
ソフトウェアテストにおける境界値や機能の網羅的テストケースの自動生成処理や、暗号の鍵空間の広さを評価するセキュリティ診断ツールなどの実装に現れます。
組み合わせの総数を先に求めれば、全探索が現実的な規模なのかを判断する材料にもなります。
これを知ると何が違って見えるのか(「数学のメガネ」として)
入力パラメータが増えたときにシステムの「組み合わせ爆発」がどのスケールで発生するかを事前に予測できるようになります。
全探索をすべきか、あるいはヒューリスティックや枝刈りを取り入れるべきかの適切な設計判断を下せます。
実装例1
処理内容
順列の全列挙
3個の要素から2個を順序を区別して選ぶすべての順列を列挙します。
Pythonでの実装例
import itertools
perms = list(itertools.permutations([1, 2, 3], 2))
print(perms)
VBAでの実装例
Sub PermutationExample()
    Dim i As Long, j As Long

    For i = 1 To 3
        For j = 1 To 3
            If i <> j Then
                Debug.Print i & "," & j
            End If
        Next j
    Next i
End Sub
JavaScriptでの実装例
const items = [1, 2, 3];
const permutations = [];

for (const a of items) {
    for (const b of items) {
        if (a !== b) permutations.push([a, b]);
    }
}

console.log(permutations);
実装例2
処理内容
組み合わせの全列挙
4個の要素から2個を順序を区別せずに選ぶすべての組み合わせを列挙します。
Pythonでの実装例
import itertools

items = ["A", "B", "C", "D"]

for combination in itertools.combinations(items, 2):
    print(combination)
VBAでの実装例
Sub CombinationExample()
    Dim items As Variant
    Dim i As Long, j As Long

    items = Array("A", "B", "C", "D")

    For i = LBound(items) To UBound(items)
        For j = i + 1 To UBound(items)
            Debug.Print items(i) & "," & items(j)
        Next j
    Next i
End Sub
JavaScriptでの実装例
const items = ["A", "B", "C", "D"];

for (let i = 0; i < items.length; i++) {
    for (let j = i + 1; j < items.length; j++) {
        console.log([items[i], items[j]]);
    }
}
実装例3(IT実務での例)
処理内容
テスト条件の組み合わせを列挙する
OS、ブラウザ、権限の候補から、確認すべきテスト条件を直積として列挙します。
👓 数学のメガネ:実務のテスト設計では、条件が増えるたびに候補数が掛け算で増えます。「組み合わせ爆発」を数える視点がテスト範囲の設計につながります。
Pythonでの実装例
import itertools

os_list = ["Windows", "macOS"]
browsers = ["Chrome", "Edge"]
roles = ["admin", "user"]

for case in itertools.product(os_list, browsers, roles):
    print(case)
VBAでの実装例
Sub TestMatrixExample()
    Dim osList As Variant, browsers As Variant, roles As Variant
    Dim i As Long, j As Long, k As Long

    osList = Array("Windows", "macOS")
    browsers = Array("Chrome", "Edge")
    roles = Array("admin", "user")

    For i = 0 To 1
        For j = 0 To 1
            For k = 0 To 1
                Debug.Print osList(i), browsers(j), roles(k)
            Next k
        Next j
    Next i
End Sub
JavaScriptでの実装例
const osList = ["Windows", "macOS"];
const browsers = ["Chrome", "Edge"];
const roles = ["admin", "user"];

for (const os of osList) {
    for (const browser of browsers) {
        for (const role of roles) {
            console.log([os, browser, role]);
        }
    }
}

12. 確率と条件付き確率

数学として何なのか(定義式)
確率は、標本空間 Ω の事象 A に対して P(A) を割り当て、0≤P(A)≤1、P(Ω)=1 などの性質を満たすものとして定義します。
事象 B が起こったという条件のもとで A が起こる確率を条件付き確率 P(A|B)=P(A∩B)/P(B)(P(B)>0)と定義します。
独立な事象では P(A∩B)=P(A)P(B) となります。
一方、条件付き確率では「Bが起きた」という新しい条件によって、Aの確率が変わることがあります。
この「条件が追加されると確率の見方が変わる」という構造は、データ分析や推論の基本になります。
直感的にはどういう構造なのか
確率は「どれくらい起こりそうか」を0から1の数で表します。
条件付き確率では、すでに分かっている情報を前提にして、もう一度確率を考えます。
たとえば「全体の中でAがどれくらいあるか」と「Bであることが分かった人の中でAがどれくらいあるか」は、同じ確率とは限りません。
データが追加されることで、考える対象となる範囲が変わる。
この視点が、確率を単なる割合計算ではなく「条件付きの推論」として捉えるポイントです。
IT(コード)ではどこに現れるのか
テキストマイニングにおけるキーワード出現率に基づくスパム判定ロジックや、特定の障害ログが発生したときにシステム全体がダウンする確率を推算するエラー分析コードに現れます。
これを知ると何が違って見えるのか(「数学のメガネ」として)
「単なる全体発生率」と「特定条件下での発生確率」を区別して考えられるようになります。
運用監視のアラート設計や障害分析でも、観測条件によって発生確率がどのように変化するかを整理し、事象同士の関連を定量的に検討するための材料になります。
実装例1
処理内容
条件付き確率の計算
1000件のデータのうち、条件を満たす集合の中でさらに別の条件を満たす確率を求めます。
Pythonでの実装例
total, spam, spam_and_keyword = 1000, 100, 80
prob_keyword_given_spam = spam_and_keyword / spam
print(prob_keyword_given_spam)
VBAでの実装例
Sub ProbabilityExample()
    Dim total As Long
    Dim spam As Long
    Dim spamAndKeyword As Long
    Dim probKeywordGivenSpam As Double

    total = 1000
    spam = 100
    spamAndKeyword = 80

    probKeywordGivenSpam = spamAndKeyword / spam

    MsgBox probKeywordGivenSpam
End Sub
JavaScriptでの実装例
const total = 1000;
const spam = 100;
const spamAndKeyword = 80;
const probKeywordGivenSpam = spamAndKeyword / spam;

console.log(probKeywordGivenSpam);
実装例2(IT実務での例)
処理内容
特定アラートが出たときの障害発生率を求める
監視ログ全体ではなく、「DB_TIMEOUTというアラートが出たケース」に条件を絞って、実際に障害へ至った割合を求めます。
👓 数学のメガネ:P(障害 | DB_TIMEOUT) を見ることで、全体の障害率とは別に「その条件が観測されたとき」のリスクを評価できます。
Pythonでの実装例
alert_count = 120
outage_with_alert = 36

p_outage_given_alert = outage_with_alert / alert_count
print(p_outage_given_alert)
VBAでの実装例
Sub ConditionalOutageExample()
    Dim alertCount As Long, outageWithAlert As Long
    Dim probability As Double

    alertCount = 120
    outageWithAlert = 36

    probability = outageWithAlert / alertCount
    Debug.Print probability
End Sub
JavaScriptでの実装例
const alertCount = 120;
const outageWithAlert = 36;

const pOutageGivenAlert = outageWithAlert / alertCount;
console.log(pOutageGivenAlert);

13. 確率分布(正規分布・二項分布など)

数学として何なのか(定義式)
確率分布は、確率変数 X がどの値をどの程度の確率で取るかを表す数学的なモデルです。
連続型の正規分布では、平均 μ、標準偏差 σ によって確率密度関数 f(x)=1/(σ√(2π)) exp(-(x-μ)2/(2σ2)) を表せます。
二項分布では、成功確率 p の試行を n 回行ったとき、成功回数 X が k になる確率を P(X=k)=nCkpk(1-p)n-k と表します。
このように確率分布は、単一の値ではなく「値がどのようにばらついて現れるか」を数学的に表現します。
直感的にはどういう構造なのか
現実のデータは、いつも同じ値になるわけではありません。
確率分布は、その「ばらつき方」に形を与える考え方です。
正規分布なら平均を中心に左右へ広がる形、二項分布なら成功・失敗を繰り返した結果としての成功回数の分布、と考えられます。
そのため、平均値だけを見るのではなく、「どの値がどれくらい現れやすいのか」というデータ全体の形を見ることができます。
IT(コード)ではどこに現れるのか
Webシステムの負荷テストツールにおけるユーザーのリクエスト発生間隔の乱数生成や、ネットワークトラフィックの変動を模倣したシミュレーションスクリプトに現れます。
これを知ると何が違って見えるのか(「数学のメガネ」として)
システムメトリクスを評価する際、「平均値」という単一の指標だけに頼る危険性がわかるようになります。
データのばらつきや外れ値の頻度を確率モデルとして把握し、実態に即したスケーリングやリソース設計が可能になります。
実装例1
処理内容
正規分布乱数によるサンプリング
正規分布に従う乱数を生成し、確率分布を持つ値をコンピューター上で扱います。
Pythonでの実装例
import random
val = random.gauss(0, 1)
print(val)
VBAでの実装例
Function NormalRandom() As Double
    Dim u1 As Double, u2 As Double

    u1 = Rnd
    Do While u1 = 0
        u1 = Rnd
    Loop
    u2 = Rnd

    NormalRandom = Sqr(-2# * Log(u1)) * Cos(2# * 3.14159265358979# * u2)
End Function

Sub NormalSampleExample()
    Randomize
    Debug.Print NormalRandom()
End Sub
JavaScriptでの実装例
function normalApprox() {
    let u1 = Math.random();
    while (u1 === 0) {
        u1 = Math.random();
    }
    const u2 = Math.random();
    return Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);
}

console.log(normalApprox());
実装例2
処理内容
二項分布の確率計算
成功確率 p の試行を n 回行ったとき、成功回数が k 回になる確率を計算します。
Pythonでの実装例
import math

n = 10
k = 6
p = 0.5

prob = math.comb(n, k) * p ** k * (1 - p) ** (n - k)
print(prob)
VBAでの実装例
Function Combination(n As Long, k As Long) As Double
    Dim i As Long
    Dim result As Double

    result = 1
    For i = 1 To k
        result = result * (n - k + i) / i
    Next i

    Combination = result
End Function

Sub BinomialExample()
    Dim n As Long, k As Long
    Dim p As Double
    Dim prob As Double

    n = 10
    k = 6
    p = 0.5

    prob = Combination(n, k) * p ^ k * (1 - p) ^ (n - k)
    Debug.Print prob
End Sub
JavaScriptでの実装例
function combination(n, k) {
    let result = 1;
    for (let i = 1; i <= k; i++) {
        result *= (n - k + i) / i;
    }
    return result;
}

const n = 10;
const k = 6;
const p = 0.5;

const prob = combination(n, k) * p ** k * (1 - p) ** (n - k);
console.log(prob);
実装例3(IT実務での例)
処理内容
レスポンスタイムの「遅い側」の割合を見る
平均値だけでなく、500msを超えたリクエストが全体の何割あるかを確認します。
👓 数学のメガネ:システム性能は平均値だけでは捉えきれません。分布の裾にある遅いリクエストの割合を見ることで、ばらつきを意識した評価になります。
Pythonでの実装例
latencies = [120, 150, 180, 220, 260, 310, 480, 520, 800, 1200]
threshold = 500

slow_rate = sum(x > threshold for x in latencies) / len(latencies)
print(slow_rate)
VBAでの実装例
Sub LatencyDistributionExample()
    Dim latencies As Variant
    Dim threshold As Double
    Dim slowCount As Long, i As Long

    latencies = Array(120, 150, 180, 220, 260, 310, 480, 520, 800, 1200)
    threshold = 500

    For i = LBound(latencies) To UBound(latencies)
        If latencies(i) > threshold Then slowCount = slowCount + 1
    Next i

    Debug.Print slowCount / (UBound(latencies) + 1)
End Sub
JavaScriptでの実装例
const latencies = [120, 150, 180, 220, 260, 310, 480, 520, 800, 1200];
const threshold = 500;

const slowCount = latencies.filter(x => x > threshold).length;
const slowRate = slowCount / latencies.length;
console.log(slowRate);

14. 統計的推定と仮説検定

数学として何なのか(定義式)
統計的推定では、母集団から得た標本を使って母平均などの未知のパラメータを推定します。
標本平均 x̄ は母平均 μ の推定量の一つです。
仮説検定では、まず帰無仮説 H0 を置き、その仮説のもとで観測した結果がどの程度起こりにくいかを検定統計量や p 値などで評価します。
たとえば2標本t検定では、2つの標本平均の差を標準誤差で規格化した t 統計量を用います。
重要なのは、標本で観測された差をそのまま「真の差」とみなすのではなく、標本抽出による偶然の変動を考慮することです。
直感的にはどういう構造なのか
少ないデータしか見られないとき、そのデータだけで全体を断定することはできません。
統計では「この程度の差は、偶然のばらつきでも起こり得るのか」を考えます。
仮説検定は「差があることを証明する」というより、帰無仮説を前提にしたときに観測結果がどの程度珍しいかを評価する手続きです。
この考え方を知ると、数字の大小だけで結論を出すのではなく、標本のばらつきや不確実性まで含めてデータを見ることができます。
IT(コード)ではどこに現れるのか
WebサービスのUI改修におけるA/Bテストの効果測定スクリプトや、新しいアルゴリズム導入前後の処理速度の差が偶然ではなく有意なものであるかを確認する検証コードに現れます。
これを知ると何が違って見えるのか(「数学のメガネ」として)
「数値が少し良くなったから改善した」という判断を、統計的な根拠なしに下すことを避けられるようになります。
帰無仮説のもとで観測結果がどの程度起こりにくいのかを評価し、観測された差をどのように解釈するかの判断材料を得られるようになります。
実装例1
処理内容
2標本t検定による平均差の評価
2つの標本の平均差を、等分散を仮定しないWelchのt検定で評価します。PythonとVBAではp値を求め、JavaScriptでは簡潔さを優先してWelchのt統計量までを計算します。
Pythonでの実装例
import scipy.stats as stats
a = [1, 2, 3]
b = [2, 3, 4]
t_stat, p_val = stats.ttest_ind(a, b, equal_var=False)
print(p_val)
VBAでの実装例
Sub TTestExample()
    Dim a As Variant
    Dim b As Variant
    Dim pVal As Double

    a = Array(1, 2, 3)
    b = Array(2, 3, 4)

    pVal = WorksheetFunction.TTest(a, b, 2, 3)
    MsgBox pVal
End Sub

※ WorksheetFunction.TTest はExcelのワークシート関数をVBAから呼び出す方法です。実行にはExcel環境が必要です。

JavaScriptでの実装例
function mean(values) {
    return values.reduce((sum, x) => sum + x, 0) / values.length;
}

function variance(values) {
    const m = mean(values);
    return values.reduce((sum, x) => sum + (x - m) ** 2, 0) / (values.length - 1);
}

const a = [1, 2, 3];
const b = [2, 3, 4];
const t = (mean(a) - mean(b)) /
    Math.sqrt(variance(a) / a.length + variance(b) / b.length);

console.log(t);
実装例2(IT実務での例)
処理内容
新旧APIのレスポンスタイムを比較する
旧APIと新APIで複数回計測したレスポンスタイムを、Welchのt検定で比較します。
👓 数学のメガネ:平均が少し違うだけで「改善した」と決めず、測定値のばらつきも含めて差を評価するのが仮説検定の実務的な使い方です。
Pythonでの実装例
from scipy import stats

old_api = [420, 390, 450, 410, 430]
new_api = [360, 340, 380, 355, 370]

t_stat, p_value = stats.ttest_ind(old_api, new_api, equal_var=False)
print(t_stat, p_value)
VBAでの実装例
Sub ApiSpeedTTestExample()
    Dim oldApi As Variant, newApi As Variant
    Dim pVal As Double

    oldApi = Array(420, 390, 450, 410, 430)
    newApi = Array(360, 340, 380, 355, 370)

    pVal = WorksheetFunction.TTest(oldApi, newApi, 2, 3)
    Debug.Print pVal
End Sub
JavaScriptでの実装例
function mean(values) {
    return values.reduce((sum, x) => sum + x, 0) / values.length;
}

function variance(values) {
    const m = mean(values);
    return values.reduce((sum, x) => sum + (x - m) ** 2, 0) / (values.length - 1);
}

const oldApi = [420, 390, 450, 410, 430];
const newApi = [360, 340, 380, 355, 370];
const t = (mean(oldApi) - mean(newApi)) /
    Math.sqrt(variance(oldApi) / oldApi.length + variance(newApi) / newApi.length);

console.log(t);

※Python版とVBA版ではp値を求めていますが、JavaScript版ではライブラリを使わず計算過程を示すため、Welchのt統計量までを求めています。


15. 情報エントロピーと圧縮

数学として何なのか(定義式)
ある事象が確率 p で起こるとき、その事象の自己情報量を I(x)=-log2p と定義します。
起こりにくい事象ほど大きな情報量を持ちます。
確率変数 X のシャノンエントロピーは H(X)=-∑ipilog2pi と定義され、1回の結果から得られる情報量の期待値を表します。
たとえば、必ず起こる事象の情報量は0ですが、確率1/4の事象なら -log2(1/4)=2 ビットです。
エントロピーは、結果の不確実性を平均的な情報量として数値化します。
直感的にはどういう構造なのか
めったに起こらないことを聞いたときほど、「そんなことが起きたのか」という驚きが大きくなります。
自己情報量は、この「驚き」を数値として表す考え方です。
反対に、いつも同じ結果になるデータには新しい情報がほとんどありません。
結果が均等に分かれて予測しにくいほど、平均的な情報量であるエントロピーは大きくなります。
この見方から、データの偏りや冗長性、圧縮可能性を数学的に考えられるようになります。
IT(コード)ではどこに現れるのか
ログデータや通信パケットのエンコード効率を評価する処理や、ハフマン符号化をはじめとするデータ圧縮・最適化アルゴリズムの内部実装に現れます。
これを知ると何が違って見えるのか(「数学のメガネ」として)
データ構造やログ設計を行う際、「どこに無駄な冗長性があり、どこが本質的な情報量を持っているか」を情報理論の観点から見抜けるようになります。
通信量削減やストレージ効率化の強力な武器になります。
実装例1
処理内容
自己情報量の計算
ある事象の確率 p から、その事象が持つ情報量 -log2(p) を計算します。
Pythonでの実装例
import math
p = 0.25
information = -math.log2(p)
print(information)
VBAでの実装例
Sub SelfInformationExample()
    Dim p As Double, info As Double
    p = 0.25
    info = -Log(p) / Log(2)
    MsgBox info
End Sub
JavaScriptでの実装例
const p = 0.25;
const information = -Math.log2(p);
console.log(information);
実装例2(IT実務での例)
処理内容
珍しいログイベントの情報量を求める
ログ10000件のうち10件しか出ていない SECURITY_ALERT の出現確率から、そのイベントの自己情報量を計算します。
👓 数学のメガネ:頻繁なログより珍しいログほど自己情報量が大きくなります。異常検知やログ分析では「珍しさ」を定量的に見る発想につながります。
Pythonでの実装例
import math

total_logs = 10000
security_alerts = 10
p = security_alerts / total_logs

information = -math.log2(p)
print(information)
VBAでの実装例
Sub RareLogInformationExample()
    Dim totalLogs As Long, securityAlerts As Long
    Dim p As Double, information As Double

    totalLogs = 10000
    securityAlerts = 10
    p = securityAlerts / totalLogs

    information = -Log(p) / Log(2)
    Debug.Print information
End Sub
JavaScriptでの実装例
const totalLogs = 10000;
const securityAlerts = 10;
const p = securityAlerts / totalLogs;

const information = -Math.log2(p);
console.log(information);

16. ベイズの定理と確率的推論

数学として何なのか(定義式)
事象 D を観測したあとで仮説 θ が成り立つ確率を事後確率 P(θ|D) とし、ベイズの定理によって P(θ|D)=P(D|θ)P(θ)/P(D) と表します。
ここで P(θ) は事前確率、P(D|θ) は尤度、P(D) はデータが得られる確率です。
つまり、最初に持っていた仮説の確率に、観測したデータとの整合性を表す尤度を掛け合わせ、データ全体が得られる確率で正規化することで、観測後の確率を求めます。
ベイズ推論は「新しい情報を得たら、それまでの確率をどう更新するか」を数学的に表す仕組みです。
直感的にはどういう構造なのか
最初から答えを固定するのではなく、「今のところこう考えている」という確率を持っておき、新しい証拠が得られたら更新します。
たとえば、ある仮説がもともとどの程度ありそうだったかと、その仮説なら今回のデータがどの程度起こりやすいかを組み合わせて、観測後の確率を計算します。
このため、ベイズの定理は「予測 → 観測 → 更新」という、データを受け取るたびに推論を更新する構造として捉えることができます。
IT(コード)ではどこに現れるのか
受信したメールの特徴量から迷惑メールかどうかを判定するベイズフィルタや、ユーザーの行動履歴などの新しいデータを受け取るたびに、推論結果を更新するレコメンドシステムのロジックに現れます。
これを知ると何が違って見えるのか(「数学のメガネ」として)
新しい観測データが得られるたびに、それまでの仮説に対する確率を更新していくという、確率的推論の仕組みを理解しやすくなります。
実装例1
処理内容
ベイズ推論(ベイズ更新)
事前確率と条件付き確率から、観測した結果のもとでの事後確率をベイズの定理で求めます。
Pythonでの実装例
p_a = 0.01
p_b_given_a = 0.9
p_b = 0.05
p_a_given_b = (p_b_given_a * p_a) / p_b
print(p_a_given_b)
VBAでの実装例
Sub BayesExample()
    Dim pa As Double, pba As Double, pb As Double
    pa = 0.01: pba = 0.9: pb = 0.05
    MsgBox (pba * pa) / pb
End Sub
JavaScriptでの実装例
const pA = 0.01;
const pBGivenA = 0.9;
const pB = 0.05;
const pAGivenB = (pBGivenA * pA) / pB;

console.log(pAGivenB);
実装例2(IT実務での例)
処理内容
監視アラートを受けた後の障害確率を更新する
通常時の障害率、障害時にアラートが出る確率、正常時にも誤ってアラートが出る確率から、アラート観測後の障害確率を求めます。
👓 数学のメガネ:「アラートが出た = 障害」と即断せず、事前確率とアラートの信頼性を組み合わせて事後確率へ更新するのがベイズの考え方です。
Pythonでの実装例
p_outage = 0.01
p_alert_given_outage = 0.90
p_alert_given_normal = 0.05

p_alert = (
    p_alert_given_outage * p_outage
    + p_alert_given_normal * (1 - p_outage)
)
p_outage_given_alert = p_alert_given_outage * p_outage / p_alert

print(p_outage_given_alert)
VBAでの実装例
Sub AlertBayesExample()
    Dim pOutage As Double
    Dim pAlertGivenOutage As Double, pAlertGivenNormal As Double
    Dim pAlert As Double, pOutageGivenAlert As Double

    pOutage = 0.01
    pAlertGivenOutage = 0.9
    pAlertGivenNormal = 0.05

    pAlert = pAlertGivenOutage * pOutage + _
             pAlertGivenNormal * (1 - pOutage)
    pOutageGivenAlert = pAlertGivenOutage * pOutage / pAlert

    Debug.Print pOutageGivenAlert
End Sub
JavaScriptでの実装例
const pOutage = 0.01;
const pAlertGivenOutage = 0.90;
const pAlertGivenNormal = 0.05;

const pAlert =
    pAlertGivenOutage * pOutage +
    pAlertGivenNormal * (1 - pOutage);
const pOutageGivenAlert = pAlertGivenOutage * pOutage / pAlert;

console.log(pOutageGivenAlert);


第4章:変化と空間を見る数学(17~20)

ITでは、データや状態が変化したり、多次元のデータを扱ったりする場面が数多くあります。
ここでは、変化の大きさと方向、そして多次元の空間を扱うための数学のメガネを揃えます。

微分は「どの方向にどれだけ変化するか」を捉え、勾配は多変数の変化を一つのベクトルとして表します。行列は複数の数値をまとめて変換する仕組みを表し、固有値・固有ベクトルは、その変換の中で保たれる特別な方向を捉えます。ベクトル空間と内積は、高次元のデータを「方向」や「近さ」という幾何学的な関係で扱う基盤になります。

こうした数学は、微積分や線形代数、最適化などを基盤として、機械学習、画像処理、コンピュータグラフィックスなど、データの変化や多次元の空間を扱う分野につながっています。

17. 微分・偏微分と勾配

数学として何なのか(定義式)
1変数関数 f(x) の導関数を f'(x)=limh→0(f(x+h)-f(x))/h と定義し、ある点での局所的な変化率を表します。
多変数関数 f(x1,...,xn) では、各変数についての偏微分を並べた ∇f=( ∂f/∂x1,...,∂f/∂xn ) を勾配といいます。
勾配は関数が最も急に増加する方向を示すベクトルです。
そのため、損失を小さくしたい場合は、勾配とは反対方向へ進むという考え方が勾配降下法につながります。
微分は「変化率」、勾配は「多次元での変化率の向きと大きさ」を扱う数学です。
直感的にはどういう構造なのか
坂道を歩くとき、「どちらへ進むと上り坂になるか」「どの方向が最も急か」を知りたくなります。
勾配は、多次元の関数に対してこれを数学的に表すものです。
損失を小さくしたいなら、最も増加する方向である勾配の反対へ少しずつ進みます。
更新式 x←x-η∇f(x) が、その考え方を表しています。
したがって機械学習のパラメータ調整は、単なる試行錯誤ではなく、「関数の傾きを計算して、より小さい方向へ移動する」という数学的な操作として見えてきます。
IT(コード)ではどこに現れるのか
機械学習モデルのパラメータを学習・更新させる「勾配降下法」の実装や、システムのパフォーマンスを改善するための最適化計算などに現れます。
これを知ると何が違って見えるのか(「数学のメガネ」として)
パラメータの調整作業が、単なる試行錯誤ではなく「多次元の誤差の傾斜(勾配)を計算し、最も傾斜を下る方向へパラメータを滑らせていく幾何学的な下降操作」として理解できるようになります。
実装例1
処理内容
勾配降下法(Gradient Descent)
f(x)=x2 の微分 f'(x)=2x を使い、現在位置から損失が小さくなる方向へxを繰り返し更新します。
Pythonでの実装例
x = 10.0
lr = 0.1
for _ in range(5):
    grad = 2 * x
    x -= lr * grad
print(x)
VBAでの実装例
Sub OptimizationExample()
    Dim x As Double, lr As Double, i As Long
    x = 10#: lr = 0.1
    For i = 1 To 5
        x = x - lr * (2 * x)
    Next i
    MsgBox x
End Sub
JavaScriptでの実装例
let x = 10.0;
const lr = 0.1;

for (let i = 0; i < 5; i++) {
    const grad = 2 * x;
    x -= lr * grad;
}

console.log(x);
実装例2(IT実務での例)
処理内容
処理パラメータをコストが小さい方向へ調整する
簡略化した性能コスト関数を使い、バッチサイズを勾配の反対方向へ少しずつ動かします。
👓 数学のメガネ:実際のチューニングでは評価関数はもっと複雑ですが、「パラメータをどちらへ動かせば評価値が下がるか」を勾配で決める考え方は同じです。
Pythonでの実装例
batch_size = 20.0
learning_rate = 0.1

for _ in range(10):
    # cost = (batch_size - 64)^2 + 100
    gradient = 2 * (batch_size - 64)
    batch_size -= learning_rate * gradient

print(batch_size)
VBAでの実装例
Sub BatchSizeTuningExample()
    Dim batchSize As Double, learningRate As Double
    Dim gradient As Double, i As Long

    batchSize = 20#
    learningRate = 0.1

    For i = 1 To 10
        gradient = 2 * (batchSize - 64)
        batchSize = batchSize - learningRate * gradient
    Next i

    Debug.Print batchSize
End Sub
JavaScriptでの実装例
let batchSize = 20.0;
const learningRate = 0.1;

for (let i = 0; i < 10; i++) {
    const gradient = 2 * (batchSize - 64);
    batchSize -= learningRate * gradient;
}

console.log(batchSize);

18. 行列と線形変換

数学として何なのか(定義式)
m×n 行列 A と n 次元ベクトル x の積 y=Ax は、ベクトルを別のベクトルへ写す線形変換を表します。
線形変換 T は T(x+y)=T(x)+T(y)、T(cx)=cT(x) を満たします。
2次元の回転なら、角度 θ に対して R=[[cosθ,-sinθ],[sinθ,cosθ]] と表せます。
行列を掛け合わせれば、複数の線形変換を一つの変換として合成できます。
平行移動は線形変換ではないため、回転・拡大縮小と同じ行列形式で扱うには同次座標を使うなどの拡張が必要になります。
直感的にはどういう構造なのか
行列は、たくさんの数値を一つずつ計算する代わりに、「まとめて変換するルール」として扱うことができます。
たとえば画像上の点を回転させる場合、点ごとに別々の公式を書くのではなく、回転行列を掛けるだけで同じ変換を適用できます。
そのため、行列を知ると、画像処理や3Dグラフィックス、機械学習で大量に行われる計算を「ベクトルを別の空間へ写す変換」として統一的に見ることができます。
IT(コード)ではどこに現れるのか
3Dコンピュータグラフィックスにおけるオブジェクトのワールド座標変換・カメラ座標変換や、ディープラーニングにおける各層の重み付け一括計算などに現れます。
これを知ると何が違って見えるのか(「数学のメガネ」として)
複雑な座標計算をバラバラの個別計算ではなく、「ベクトルに対する行列の積」として統一的に捉えられるようになります。
回転や拡大縮小を行列として扱い、同次座標を使えば平行移動も含めて、複数の空間変換を一つの行列として合成できます。
実装例1
処理内容
行列・ベクトル積による線形変換
行列とベクトルを掛け合わせ、行列による線形変換を数値計算として実行します。
Pythonでの実装例
import numpy as np
matrix = np.array([[1, 2], [3, 4]])
vector = np.array([1, 1])
print(np.dot(matrix, vector))
VBAでの実装例
Sub MatrixVectorMultiplyExample()
    Dim matrix(1 To 2, 1 To 2) As Double
    Dim vector(1 To 2) As Double
    Dim result(1 To 2) As Double

    matrix(1, 1) = 1#: matrix(1, 2) = 2#
    matrix(2, 1) = 3#: matrix(2, 2) = 4#

    vector(1) = 1#: vector(2) = 1#

    result(1) = matrix(1, 1) * vector(1) + matrix(1, 2) * vector(2)
    result(2) = matrix(2, 1) * vector(1) + matrix(2, 2) * vector(2)

    Debug.Print result(1)
    Debug.Print result(2)
End Sub
JavaScriptでの実装例
const matrix = [[1, 2], [3, 4]];
const vector = [1, 1];

const result = matrix.map(row =>
    row.reduce((sum, value, i) => sum + value * vector[i], 0)
);

console.log(result);
実装例2(IT実務での例)
処理内容
画像上の座標を縮小後の座標へ変換する
1600×1200の画像を50%に縮小するとき、画像上の点 (800, 600) を行列で新しい座標へ変換します。
👓 数学のメガネ:画像処理では、各点を個別の式で扱うのではなく、座標ベクトルに同じ変換行列を適用することで処理を統一できます。
Pythonでの実装例
import numpy as np

scale = np.array([[0.5, 0.0], [0.0, 0.5]])
point = np.array([800, 600])

new_point = scale @ point
print(new_point)
VBAでの実装例
Sub ImageScaleExample()
    Dim x As Double, y As Double
    Dim scale As Double
    Dim newX As Double, newY As Double

    x = 800#: y = 600#
    scale = 0.5

    newX = scale * x + 0 * y
    newY = 0 * x + scale * y

    Debug.Print newX, newY
End Sub
JavaScriptでの実装例
const scale = [[0.5, 0.0], [0.0, 0.5]];
const point = [800, 600];

const newPoint = scale.map(row =>
    row.reduce((sum, value, i) => sum + value * point[i], 0)
);

console.log(newPoint);

19. 固有値・固有ベクトル

数学として何なのか(定義式)
正方行列 A に対して、0ではないベクトル v が A v = λ v を満たすとき、λ を固有値、v を固有ベクトルといいます。
つまり、行列による変換を行っても、固有ベクトルは同一直線上に保たれ、λ に応じて伸縮します。λ が負の場合は向きが反転します。
固有値は det(A-λI)=0 を満たす値として求めることができ、対応する固有ベクトルは (A-λI)v=0 を解くことで求められます。
直感的にはどういう構造なのか
行列による変換では、一般にはベクトルの向きも長さも変わります。
その中に「変換後も同一直線上に保たれる特別な方向」が存在することがあります。
その特別な方向を表すのが固有ベクトルで、どれだけ伸縮するかを表す数が固有値です。固有値が負なら向きは反転します。
行列を単なる大量の掛け算としてではなく、「空間の中の方向をどう変化させるか」という観点から見るための数学になります。
IT(コード)ではどこに現れるのか
行列を繰り返し適用して重要な方向を求める計算、グラフのランキング、主成分分析(PCA)などに現れます。
ここで重要なのは個別の応用技術を覚えることではなく、「変換の中に保たれる特別な方向がある」という固有値・固有ベクトルの考え方です。
これを知ると何が違って見えるのか(「数学のメガネ」として)
行列を「数値を別の数値へ変換する表」として見るだけでなく、「空間の中の方向ごとに異なる作用を持つ変換」として見ることができます。
特に、繰り返し変換したときにどの方向が残り、どの方向が強く伸びるのかという問題を、固有値・固有ベクトルという共通の数学として捉えられるようになります。
実装例1
処理内容
固有値・固有ベクトルの検証
2×2行列と固有ベクトルを使い、A v と λ v が一致することを数値的に確認します。
Pythonでの実装例
import numpy as np

A = np.array([[2, 1], [1, 2]], dtype=float)
v = np.array([1, 1], dtype=float)
lam = 3.0

print(A @ v)
print(lam * v)
print(np.allclose(A @ v, lam * v))
VBAでの実装例
Sub EigenvectorCheckExample()
    Dim a11 As Double, a12 As Double
    Dim a21 As Double, a22 As Double
    Dim vx As Double, vy As Double, lambda As Double
    Dim av1 As Double, av2 As Double

    a11 = 2#: a12 = 1#
    a21 = 1#: a22 = 2#
    vx = 1#: vy = 1#: lambda = 3#

    av1 = a11 * vx + a12 * vy
    av2 = a21 * vx + a22 * vy

    Debug.Print av1, av2
    Debug.Print lambda * vx, lambda * vy
    Debug.Print Abs(av1 - lambda * vx) < 0.000000000001 And _
                Abs(av2 - lambda * vy) < 0.000000000001
End Sub
JavaScriptでの実装例
const A = [[2, 1], [1, 2]];
const v = [1, 1];
const lambda = 3;

const Av = [
    A[0][0] * v[0] + A[0][1] * v[1],
    A[1][0] * v[0] + A[1][1] * v[1]
];
const lambdaV = v.map(x => lambda * x);

console.log(Av);
console.log(lambdaV);
console.log(Av.every((x, i) => Math.abs(x - lambdaV[i]) < 1e-12));
実装例2
処理内容
べき乗法(Power Iteration)
一定の条件を満たす場合、ベクトルに行列を繰り返し掛けて正規化することで、絶対値最大の固有値に対応する固有ベクトルへ近づけます。
Pythonでの実装例
import numpy as np

A = np.array([[2, 1], [1, 2]], dtype=float)
v = np.array([1.0, 0.2])

for _ in range(20):
    v = A @ v
    v = v / np.linalg.norm(v)

print(v)
VBAでの実装例
Sub PowerIterationExample()
    Dim a11 As Double, a12 As Double
    Dim a21 As Double, a22 As Double
    Dim x As Double, y As Double, nx As Double, ny As Double
    Dim norm As Double, i As Long

    a11 = 2#: a12 = 1#
    a21 = 1#: a22 = 2#
    x = 1#: y = 0.2

    For i = 1 To 20
        nx = a11 * x + a12 * y
        ny = a21 * x + a22 * y
        norm = Sqr(nx * nx + ny * ny)
        x = nx / norm
        y = ny / norm
    Next i

    Debug.Print x, y
End Sub
JavaScriptでの実装例
const A = [[2, 1], [1, 2]];
let v = [1, 0.2];

for (let i = 0; i < 20; i++) {
    const x = A[0][0] * v[0] + A[0][1] * v[1];
    const y = A[1][0] * v[0] + A[1][1] * v[1];
    const norm = Math.hypot(x, y);
    v = [x / norm, y / norm];
}

console.log(v);
実装例3(IT実務での例)
処理内容
リンク構造からページの重要度を反復計算する
3ページのリンク遷移を行列で表し、スコアベクトルへ繰り返し掛けることで、リンク構造の中で相対的に重要なページを求めます。
👓 数学のメガネ:ランキング計算では、行列を繰り返し適用したときに残る方向が重要になります。固有ベクトルは「ネットワーク全体で安定するスコア」の考え方につながります。
Pythonでの実装例
import numpy as np

transition = np.array([
    [0.0, 0.5, 1.0],
    [0.5, 0.0, 0.0],
    [0.5, 0.5, 0.0],
])
rank = np.array([1/3, 1/3, 1/3])

for _ in range(20):
    rank = transition @ rank

print(rank)
VBAでの実装例
Sub PageRankLikeExample()
    Dim m(1 To 3, 1 To 3) As Double
    Dim rank(1 To 3) As Double, nextRank(1 To 3) As Double
    Dim i As Long, j As Long, k As Long

    m(1, 1) = 0: m(1, 2) = 0.5: m(1, 3) = 1
    m(2, 1) = 0.5: m(2, 2) = 0: m(2, 3) = 0
    m(3, 1) = 0.5: m(3, 2) = 0.5: m(3, 3) = 0
    rank(1) = 1 / 3: rank(2) = 1 / 3: rank(3) = 1 / 3

    For k = 1 To 20
        For i = 1 To 3
            nextRank(i) = 0
            For j = 1 To 3
                nextRank(i) = nextRank(i) + m(i, j) * rank(j)
            Next j
        Next i
        For i = 1 To 3
            rank(i) = nextRank(i)
        Next i
    Next k

    Debug.Print rank(1), rank(2), rank(3)
End Sub
JavaScriptでの実装例
const transition = [
    [0.0, 0.5, 1.0],
    [0.5, 0.0, 0.0],
    [0.5, 0.5, 0.0]
];
let rank = [1 / 3, 1 / 3, 1 / 3];

for (let k = 0; k < 20; k++) {
    rank = transition.map(row =>
        row.reduce((sum, value, i) => sum + value * rank[i], 0)
    );
}

console.log(rank);

20. ベクトル空間と内積

数学として何なのか(定義式)
ベクトル空間 V は、ベクトル同士の加法と、スカラーによる乗法が定義され、それらが一定の公理を満たす集合として定義されます。
2つのベクトル a=(a1,...,an)、b=(b1,...,bn) の内積は a·b=∑i=1naibi で定義されます。
内積は a·b=|a||b|cosθ とも表せるため、二つのベクトルの向きの関係を測ることができます。
特に、ベクトルを正規化すると、内積によってコサイン類似度を表せます。
ベクトル空間は、多次元のデータを「点」や「方向」として扱うための数学的な枠組みです。
直感的にはどういう構造なのか
ベクトルを「数字の並び」ではなく、高次元空間の中の矢印や位置として考えると、内積の意味が見えてきます。
内積の値はベクトルの長さにも影響されますが、長さを1に正規化したベクトル同士なら、同じ方向ほど内積は1に近く、直角なら0、反対方向なら-1になります。
このように正規化すれば、内積によって「向きがどれくらい似ているか」を比較できます。
このため、文章や画像などをベクトルに変換すると、単純な文字一致ではなく「ベクトルの方向がどれくらい近いか」という幾何学的な比較が可能になります。
IT(コード)ではどこに現れるのか
検索エンジン、LLMのRAG(検索拡張生成)、およびレコメンドシステムにおけるベクトル埋め込み表現同士の類似度探索ロジックなどに現れます。
これを知ると何が違って見えるのか(「数学のメガネ」として)
文字の単なる一致判定(キーワード検索)を超えて、テキストや画像などの複雑な概念を「高次元空間におけるベクトルの位置関係・類似度指標」として扱えるようになります。
実装例1
処理内容
内積(ドット積)の計算
2つのベクトルの各成分を掛けて足し合わせ、内積を計算します。
Pythonでの実装例
import numpy as np
v1 = np.array([1, 2, 3])
v2 = np.array([2, 4, 6])
dot_prod = np.dot(v1, v2)
print(dot_prod)
VBAでの実装例
Sub DotProductExample()
    Dim v1(0 To 2) As Double, v2(0 To 2) As Double
    Dim dotProd As Double

    v1(0) = 1: v1(1) = 2: v1(2) = 3
    v2(0) = 2: v2(1) = 4: v2(2) = 6

    dotProd = v1(0) * v2(0) + v1(1) * v2(1) + v1(2) * v2(2)
    MsgBox dotProd
End Sub
JavaScriptでの実装例
const v1 = [1, 2, 3];
const v2 = [2, 4, 6];

const dotProd = v1.reduce((sum, value, i) => sum + value * v2[i], 0);
console.log(dotProd);
実装例2(IT実務での例)
処理内容
検索文と文書ベクトルのコサイン類似度を比較する
検索文を表すベクトルと複数の文書ベクトルのコサイン類似度を計算し、最も方向が近い文書を探します。
👓 数学のメガネ:RAGやベクトル検索では、文章そのものを比較する代わりに、埋め込みベクトルの方向の近さを内積・コサイン類似度で評価します。
Pythonでの実装例
import math

query = [0.8, 0.1, 0.4]
documents = {
    "manual": [0.9, 0.1, 0.3],
    "invoice": [0.1, 0.9, 0.2],
    "faq": [0.7, 0.2, 0.5],
}

def cosine(a, b):
    dot = sum(x * y for x, y in zip(a, b))
    norm_a = math.sqrt(sum(x * x for x in a))
    norm_b = math.sqrt(sum(x * x for x in b))
    return dot / (norm_a * norm_b)

for name, vector in documents.items():
    print(name, cosine(query, vector))
VBAでの実装例
Function CosineSimilarity(a As Variant, b As Variant) As Double
    Dim i As Long
    Dim dot As Double, normA As Double, normB As Double

    For i = LBound(a) To UBound(a)
        dot = dot + a(i) * b(i)
        normA = normA + a(i) * a(i)
        normB = normB + b(i) * b(i)
    Next i

    CosineSimilarity = dot / (Sqr(normA) * Sqr(normB))
End Function

Sub VectorSearchExample()
    Dim query As Variant
    query = Array(0.8, 0.1, 0.4)

    Debug.Print "manual", CosineSimilarity(query, Array(0.9, 0.1, 0.3))
    Debug.Print "invoice", CosineSimilarity(query, Array(0.1, 0.9, 0.2))
    Debug.Print "faq", CosineSimilarity(query, Array(0.7, 0.2, 0.5))
End Sub
JavaScriptでの実装例
function cosine(a, b) {
    const dot = a.reduce((sum, x, i) => sum + x * b[i], 0);
    const normA = Math.sqrt(a.reduce((sum, x) => sum + x * x, 0));
    const normB = Math.sqrt(b.reduce((sum, x) => sum + x * x, 0));
    return dot / (normA * normB);
}

const query = [0.8, 0.1, 0.4];
const documents = {
    manual: [0.9, 0.1, 0.3],
    invoice: [0.1, 0.9, 0.2],
    faq: [0.7, 0.2, 0.5]
};

for (const [name, vector] of Object.entries(documents)) {
    console.log(name, cosine(query, vector));
}


おわりに:数学を知ると、ITの見え方が変わる

プログラムを書くために、数学をすべて知っている必要はありません。
実際、数学を意識することなく、多くのプログラムを書くことができます。
それでも、数学を知ることで見えてくるものがあります。

論理を知れば、条件分岐を単なる構文ではなく、条件と結果の関係として捉えられるようになります。
集合や写像を知れば、データの抽出や変換を数学的な構造として見ることができます。
グラフを知れば、ネットワークや依存関係を「点と線の構造」として捉えられます。
確率や統計を知れば、不確実なデータを扱うときに、その背後にある考え方が見えてきます。
線形代数を知れば、多次元のデータや変換を「空間」として見ることができます。

本稿では、数学的な構造を直接確認するコードだけでなく、在庫更新、マスタ突合、障害分析、テスト設計、ランキング、ベクトル検索など、IT実務に近いコードも見てきました。
一見すると普通の業務処理でも、数学のメガネをかけると、その背後に漸化式、集合、グラフ、確率、行列といった共通の構造が見えてきます。

こうした知識は、必ずしも日々のプログラミングで数式として直接使うものではありません。
しかし、知っていることで、同じコードやシステムが少し違って見えてきます。
数学を学ぶことは、計算できることを増やすだけではありません。
ITの中にある構造を見つけるための「見方」を増やすことでもあります。

そして当然ながら、数学はここで終わりではありません。
むしろ、本稿で取り上げた20の概念は、数学全体から見れば入り口の、そのさらに手前にあるものにすぎません。
離散数学、線形代数、微積分、確率・統計をさらに深く学んでいけば、その先には数値解析、最適化、情報理論、代数学など、ITやコンピュータサイエンスにつながる多くの数学があります。

だからといって、最初からすべてを理解しようとする必要はありません。
プログラムを書いていて「なぜこうなるのだろう」と疑問を持ったとき、アルゴリズムを見て「この背後にはどんな構造があるのだろう」と考えたとき、その都度、必要な数学へ戻って学べばよいのです。

コードから数学へ行き、数学を知ってもう一度コードを見る。
その往復を繰り返すたびに、以前は単なる処理にしか見えなかったものの中に、新しい構造が見えてくるはずです。

本稿の20選が、数学を「難しい計算の世界」として避けるのではなく、ITをより深く理解するための道具として学び始めるきっかけになれば幸いです。

数学のメガネは、まだ20個しかありません。
その先には、もっと多くの見方があります。




同じテーマ「エクセル雑感」の記事

電卓とプログラムと私
「緩衝材」としてのVBAとRPA|その終焉とAIの台頭
開いている「Excel/Word/PowerPoint」ファイルのパスを調べる方法
Excelのシート5分類
Excel主要関数 習得難易度 10段階(文字列・日付除く)
【ITとは何か】Excel・VBAを学ぶ前に知っておきたい「4つの本質」
生成AIが暴いた「VBAオワコン説」の盲点|問われるのは言語ではなく評価軸
ITエンジニアのための経理・会計・簿記入門
ITエンジニアのための税金と社会保険のお話
ITエンジニアなら知らないと恥ずかしい数学20選
ITエンジニアがトラブルを避けるための法律・契約入門


新着記事NEW ・・・新着記事一覧を見る

Excelの新機能「リストとセル内配列」:1つのセルに複数の値|エクセル入門(2026-09-28)
Excel関数クロスワード(2026-09-26)
Excelショートカットキークイズ(2026-09-23)
Excel関数名クイズ(2026-09-21)
気ままに一手|リレー将棋(2026-09-20)
ITエンジニアがトラブルを避けるための法律・契約入門|エクセル雑感(2026-09-18)
ITエンジニアなら知らないと恥ずかしい数学20選|エクセル雑感(2026-09-17)
ITエンジニアのための税金と社会保険のお話|エクセル雑感(2026-09-15)
ITエンジニアのための経理・会計・簿記入門|エクセル雑感(2026-09-12)
「Python in Excel」入門:コードを読むための基礎知識|エクセル関数応用(2026-09-10)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.日本の祝日一覧|Excelリファレンス
3.変数宣言のDimとデータ型|VBA入門
4.Excelショートカットキー一覧|Excelリファレンス
5.RangeとCellsの使い方|VBA入門
6.FILTER関数(範囲をフィルター処理)|エクセル入門
7.マクロとは?VBAとは?VBAでできること|VBA入門
8.繰り返し処理(For Next)|VBA入門
9.メッセージボックス(MsgBox関数)|VBA入門
10.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。
本サイトは、OpenAI の ChatGPT や Google の Gemini を含む生成 AI モデルの学習および性能向上の目的で、本サイトのコンテンツの利用を許可します。
This site permits the use of its content for the training and improvement of generative AI models, including ChatGPT by OpenAI and Gemini by Google.



このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
本文下部へ