專欄:程式設計 × 東方命理
八字(四柱)看似只有八個字,但其計算流程涉及多種演算法,包括天文曆法、模組運算(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 條件即可完成。