什麼是大衍筮法?《易經》五十蓍草的古代筮法演算法

1. 起源

大衍筮法(大衍法,Dà Yǎn Fǎ)是目前仍可考的《易經》最古老筮法,記載於《周易・繫辭傳》,約成書於戰國時期(西元前 300~200 年)。

《繫辭傳》原文:

大衍之數五十,其用四十有九。

拼音:

Dà yǎn zhī shù wǔshí, qí yòng sìshí yǒu jiǔ.

意為:

大衍之數為五十,實際操作時使用四十九。

另一段重要文字:

分而為二以象兩,掛一以象三,揲之以四以象四時,歸奇於扐以象閏。五歲再閏,故再扐而後掛。

這段文字完整描述了大衍筮法的核心流程。


2. 宇宙哲學的象徵

大衍筮法的每一個步驟,都對應著《易經》的宇宙觀。

  • 五十根蓍草:象徵大衍之數,代表天地萬物的總體。
  • 抽出一根不用:象徵太極(太極),代表未分化的本源。
  • 使用四十九根:象徵萬物由太極而生。
  • 分成兩束:象徵兩儀(陰陽、天地)。
  • 取出一根:象徵三才(天地人)。
  • 每四根一數:象徵四時(春、夏、秋、冬)。
  • 保留餘數:象徵閏月

因此,

整個起卦過程本身,就是《易經》宇宙觀的具體呈現。


3. 十八變流程(六爻 × 三變)

《易經》一卦共有六爻。

每一爻必須經過三次變化(三變)。

因此:

6 × 3 = 18 次操作

3.1 一次變化

每一次變化包含以下步驟:

  1. 取目前剩餘的蓍草(第一次為四十九根)。
  2. 任意分為左右兩束。
  3. 從右束取出一根,置於指間,象徵三才。
  4. 左束每四根一數,留下餘數。
  5. 右束亦每四根一數,留下餘數。
  6. 將所有餘數合計,即為本次移除的蓍草數。

3.2 每次可能出現的餘數

第一次變化:

  • 5
  • 9

第二次變化:

  • 4
  • 8

第三次變化:

  • 4
  • 8

3.3 求得一爻

三次變化後,

總共移除的蓍草數只可能為:

  • 13
  • 17
  • 21
  • 25

最後剩餘:

  • 36 ÷ 4 = 9 → 老陽(動陽)
  • 32 ÷ 4 = 8 → 少陰(靜陰)
  • 28 ÷ 4 = 7 → 少陽(靜陽)
  • 24 ÷ 4 = 6 → 老陰(動陰)

4. 機率分布並非平均

大衍筮法與三枚銅錢法最大的不同,

就在於其機率分布。

# 大衍筮法
probs = {
    6: 1/16,
    7: 5/16,
    8: 7/16,
    9: 3/16,
}

即:

| 爻 | 機率 | |----|------:| | 老陰(6) | 6.25% | | 少陽(7) | 31.25% | | 少陰(8) | 43.75% | | 老陽(9) | 18.75% |

相比之下,

三枚銅錢法:

coin_probs = {
    6: 1/8,
    7: 3/8,
    8: 3/8,
    9: 1/8,
}

即:

| 爻 | 機率 | |----|------:| | 老陰(6) | 12.5% | | 少陽(7) | 37.5% | | 少陰(8) | 37.5% | | 老陽(9) | 12.5% |

大衍筮法具有:

1:5:7:3

的分布,

因此少陰出現最頻繁,

反映了《易經》陰陽消長的思想。


5. 演算法實作

5.1 Python

import random

def yarrow_one_change:
    left = random.randint
    right = n_stalks - left

    right -= 1
    hand = 1

    left_rem = left % 4 or 4
    right_rem = right % 4 or 4

    return hand + left_rem + right_rem


def yarrow_one_line():
    stalks = 49

    for _ in range(3):
        stalks -= yarrow_one_change

    return stalks // 4


def yarrow_hexagram():
    return [yarrow_one_line() for _ in range(6)]

5.2 JavaScript

function yarrowOneChange {
  const left = Math.floor(Math.random() * (nStalks - 1)) + 1;
  let right = nStalks - left - 1;

  const leftRem = left % 4 || 4;
  const rightRem = right % 4 || 4;

  return 1 + leftRem + rightRem;
}

function yarrowOneLine() {
  let stalks = 49;

  for let i = 0; i < 3; i++ {
    stalks -= yarrowOneChange;
  }

  return stalks / 4;
}

function yarrowHexagram() {
  return Array.from{ length: 6 }, () => yarrowOneLine();
}

5.3 C

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int yarrow_one_change {
    int left = 1 + rand() % ;
    int right = n_stalks - left - 1;

    int left_rem = left % 4;
    if  left_rem = 4;

    int right_rem = right % 4;
    if  right_rem = 4;

    return 1 + left_rem + right_rem;
}

int yarrow_one_line {
    int stalks = 49;

    for int i = 0; i &lt; 3; i++
        stalks -= yarrow_one_change;

    return stalks / 4;
}

6. 與其他起卦方法比較

| 方法 | 特點 | |------|------| | 大衍筮法(蓍草法) | 五十根蓍草、十八變、機率不均,最具傳統性與儀式感。 | | 三枚銅錢法 | 每爻擲三枚銅錢,快速、容易操作,機率為 1:3:3:1。 | | 六枚銅錢法 | 一次擲六枚銅錢即可得到整卦,效率最高,但較少見於傳統文獻。 | | 梅花易數 | 由邵雍創立,以時間、數字、事件起卦,不需任何器具。 |


7. QuizzMan 中的大衍筮法

QuizzMan 的《易經》系統(lab.quizzman.com)實作了完整的大衍筮法,包含:

  • 完整動畫模擬:呈現四十九根蓍草的分束、計數與三變流程,完整視覺化十八變。
  • 密碼學安全亂數:使用 CSPRNG(如 crypto.getRandomValues())產生隨機分束,而非 Math.random()
  • 機率驗證:經過百萬次以上模擬,結果符合理論分布(6.25%、31.25%、43.75%、18.75%)。
  • 雙模式比較:可同時比較大衍筮法與三枚銅錢法,觀察兩者在動爻比例與機率分布上的差異。