专栏:程式设计 × 东方命理
八字(四柱)看似只有八个字,但其计算流程涉及多种演算法,包括天文历法、模组运算(Modular Arithmetic)以及大量查表(Lookup Table)。本文将从程式设计角度,介绍八字天干地支与藏干的核心计算方式。
1. 年柱——以立春为分界
最常见的错误,就是以农历新年(春节)作为干支年的起点。
实际上,八字中的干支年是以立春(立春)为界,而不是春节。立春通常落在每年阳历 2 月 3~5 日之间。
function yearPillar {
const lichXuan = findSolarTerm(315, solarDate.year); // 315° = 立春
const year = solarDate < lichXuan
? solarDate.year - 1
: solarDate.year;
return {
stem: STEMS[(year - 4) % 10],
branch: BRANCHES[(year - 4) % 12]
};
}
其中:
- 315° 对应二十四节气中的立春。
- 若出生时间早于立春,则仍属前一年干支。
- 若出生时间在立春之后,则进入新的干支年。
2. 月柱——由节气决定
八字中的月份并不是依照农历月份,而是依照节气(节气)。
每一个月都从一个「节」开始,而不是「中气」。
例如:
- 寅月:立春 → 惊蛰
- 卯月:惊蛰 → 清明
- 之后依序对应二十四节气。
月干则依照五虎遁(五虎遁)推算。
const NGU_HO_DON = {
'甲': '丙', '己': '丙',
'乙': '戊', '庚': '戊',
'丙': '庚', '辛': '庚',
'丁': '壬', '壬': '壬',
'戊': '甲', '癸': '甲',
};
也就是说:
年干决定寅月的天干,再依序推算其余十一个月份。
3. 日柱——Julian Day Number
日柱没有简单的数学公式。
原因在于:
六十甲子循环与公历年份并不整除。
因此,目前最常见的方法是利用 Julian Day Number(儒略日数) 作为连续时间基准。
function dayPillar(year, month, day) {
const jdn = julianDayNumber(year, month, day);
const idx = (jdn + 9) % 60;
return {
stem: STEMS[idx % 10],
branch: BRANCHES[idx % 12]
};
}
其中:
- 先将日期换算为 Julian Day Number。
- 加上固定 offset。
- 再映射回六十甲子循环。
4. 时柱——五鼠遁
时柱的推算方式与月柱相似。
其天干并非固定,而是依照日干,透过五鼠遁(五鼠遁)规则推算。
一天共分为十二个时辰,每个时辰约两小时:
- 子时:23:00–01:00
- 丑时:01:00–03:00
- …
- 亥时:21:00–23:00
只要确定:
- 日干
- 出生时辰
即可得到完整的时柱。
5. 藏干——Lookup Table
藏干属于固定资料,不需要推导,而是直接查表。
每个地支包含一至三个藏干,并具有不同权重。
const TANG_CAN = {
'子': [['癸', 100]],
'丑': [['己', 60], ['癸', 30], ['辛', 10]],
'寅': [['甲', 60], ['丙', 30], ['戊', 10]],
'卯': [['乙', 100]],
'辰': [['戊', 60], ['乙', 30], ['癸', 10]],
'巳': [['丙', 60], ['庚', 30], ['戊', 10]],
'午': [['丁', 70], ['己', 30]],
'未': [['己', 60], ['丁', 30], ['乙', 10]],
'申': [['庚', 60], ['壬', 30], ['戊', 10]],
'酉': [['辛', 100]],
'戌': [['戊', 60], ['辛', 30], ['丁', 10]],
'亥': [['壬', 70], ['甲', 30]],
};
例如:
- 子:癸(100%)
- 寅:甲(60%)、丙(30%)、戊(10%)
- 申:庚(60%)、壬(30%)、戊(10%)
程式只需依据地支查表即可取得所有藏干资讯。
6. 十神——Relationship Matrix
十神本质上是一个关系矩阵(Relationship Matrix)。
它描述:
- 日主(Day Master)
- 与其他天干之间的关系。
判断依据只有三项:
- 是否同五行。
- 五行之间的生克关系。
- 是否同阴阳。
因此,整个十神判定逻辑通常只需要一个函式,以及三个主要的 if-else 条件即可完成。