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

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%)。
  • 双模式比较:可同时比较大衍筮法与三枚铜钱法,观察两者在动爻比例与机率分布上的差异。