详解如何计算四柱八字

国学元精 2024-03-26 21:00:41
计算八字的算法研究

本文用python的代码实现了计算八字,这是自己开发的,开放出来供大家研究学习。

以下也是基于jupyter notebook导出的,所以,保持原样,可读性更高。如果不是技术开发人员阅读可能会有些障碍,不过,那就pass掉代码块就行了。

首先,要想算出准备八字,就要搞清楚临界点的问题。比如,2024年是甲辰,但当输入2024.1.1时,输出却变成了“癸卯甲子甲子甲子”。这是为什么,因为,目前农历(阴历)还未过2023年。所以,在计算时要先把年从阳历转成阴历。

所以,先从这个小算法开始。

In [80]:

from lunardate import LunarDatefrom datetime import datetimedef convert_solar_to_lunar(year, month, day): solar_date = datetime(year, month, day) lunar_date = LunarDate.fromSolarDate(solar_date.year, solar_date.month, solar_date.day) return lunar_date

In [82]:

solar_year = 2024solar_month = 1solar_day = 1lunar_date = convert_solar_to_lunar(solar_year, solar_month, solar_day)print(f"阳历 {solar_year}-{solar_month:02d}-{solar_day:02d} 对应的农历是 {lunar_date.year}年{lunar_date.month}月{lunar_date.day}日")阳历 2024-01-01 对应的农历是 2023年11月20日

Look,我们搞定了阳历转阴历后,在后面的算法就要引用它了。下面就是完整的一段核心算法。入口的函数就是get_bazi()

In [83]:

def get_bazi(year, month, day, birth): # 首先要年转成阴历,并且只在计算年柱时用阴历 lunar_date = convert_solar_to_lunar(year, month, day) only4y = lunar_date.year # 计算天干地支纪年法中的年柱 year柱子 = get_year_column(only4y) # 计算天干地支纪年法中的月柱 month柱子 = get_mon_column(year, month) # 计算天干地支纪年法中的日柱 day柱子 = get_day_column(year, month, day,birth) # 计算天干地支纪年法中的时柱 time柱子 = get_time_column(year, month, day, birth) return year柱子 + month柱子 + day柱子 + time柱子def get_year_column_1(year): # 天干地支纪年法中的天干 tiangan = [ "庚", "辛", "壬", "癸","甲", "乙", "丙", "丁", "戊", "己"] # 天干地支纪年法中的地支 dizhi = ["申", "酉", "戌", "亥","子", "丑", "寅", "卯", "辰", "巳", "午", "未"] # 计算天干 tiangan_index = year % 10 tiangan = tiangan[tiangan_index] # 计算地支 dizhi_index = year % 12 dizhi = dizhi[dizhi_index] return f"{tiangan}{dizhi}"def get_year_column(year): # 计算天干 tiangan = ["甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"] # 计算地支 dizhi = ["子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"] # 计算天干 tiangan_index = (year - 4) % 10 tiangan = tiangan[tiangan_index] # 计算地支 dizhi_index = (year - 4) % 12 dizhi = dizhi[dizhi_index] return f"{tiangan}{dizhi}"def get_mon_column(year, month): # 计算天干 tiangan = ["甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"] # 计算地支 dizhi = ["子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"] # 计算天干 tiangan_index = (year - 4) % 10 midMonth = tiangan_index * 2 + month midMonth = midMonth % 10 # 平闰年校验 if year % 4 == 0 and year % 100 != 0 or year % 400 == 0: # print(year, '是闰年') if month == 1 or month == 2: midMonth = midMonth - 1 month = month - 1 tiangan = tiangan[midMonth] dizhi = dizhi[month] return f"{tiangan}{dizhi}"def get_day_column(year, month, day, birthtime): # 查表 # 创建一个空字典 calendar = {} # 填充数据 calendar[1] = "甲子" calendar[2] = "乙丑" calendar[3] = "丙寅" calendar[4] = "丁卯" calendar[5] = "戊辰" calendar[6] = "己巳" calendar[7] = "庚午" calendar[8] = "辛未" calendar[9] = "壬申" calendar[10] = "癸酉" calendar[11] = "甲戌" calendar[12] = "乙亥" calendar[13] = "丙子" calendar[14] = "丁丑" calendar[15] = "戊寅" calendar[16] = "己卯" calendar[17] = "庚辰" calendar[18] = "辛巳" calendar[19] = "壬午" calendar[20] = "癸未" calendar[21] = "甲申" calendar[22] = "乙酉" calendar[23] = "丙戌" calendar[24] = "丁亥" calendar[25] = "戊子" calendar[26] = "己丑" calendar[27] = "庚寅" calendar[28] = "辛卯" calendar[29] = "壬辰" calendar[30] = "癸巳" calendar[31] = "甲午" calendar[32] = "乙未" calendar[33] = "丙申" calendar[34] = "丁酉" calendar[35] = "戊戌" calendar[36] = "己亥" calendar[37] = "庚子" calendar[38] = "辛丑" calendar[39] = "壬寅" calendar[40] = "癸卯" calendar[41] = "甲辰" calendar[42] = "乙巳" calendar[43] = "丙午" calendar[44] = "丁未" calendar[45] = "戊申" calendar[46] = "己酉" calendar[47] = "庚戌" calendar[48] = "辛亥" calendar[49] = "壬子" calendar[50] = "癸丑" calendar[51] = "甲寅" calendar[52] = "乙卯" calendar[53] = "丙辰" calendar[54] = "丁巳" calendar[55] = "戊午" calendar[56] = "己未" calendar[57] = "庚申" calendar[58] = "辛酉" calendar[59] = "壬戌" calendar[60] = "癸亥" dicf2 = {} dicf2[18] = 25 dicf2[19] = 9 dicf2[20] = 54 dicf2[21] = 39 dicmon = {} dicmon[1]=1 dicmon[4]=1 dicmon[5]=1 dicmon[3]=0 dicmon[2]=2 dicmon[6]=2 dicmon[7]=2 dicmon[8]=3 dicmon[9]=4 dicmon[10]=4 dicmon[11]=5 dicmon[12]=5 yearfront2 = int(str(year)[:2]) yearlast2 = int(str(year)[-2:]) isdoublemonth = 30 if month % 2 == 0 else 0 # (month/2==0)?0:30 # 主公式 ret = yearlast2 * 5 + int(yearlast2/4) + dicf2[yearfront2] + day + isdoublemonth + dicmon[month] # 平闰年校验 if year % 4 == 0 and year % 100 != 0 or year % 400 == 0: # print(year, '是闰年') if month == 1 or month == 2: ret = ret - 1 # else: # print(year, '是平年') retindex, retyu = divide_remainder(ret, 60) if retyu: retindex = retyu # 计算天干 # tiangan = ["甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"] # 计算地支 # dizhi = ["子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"] # 计算天干 # tiangan_index = (year - 4) % 10 # tiangan = tiangan[tiangan_index] # 计算地支 # dizhi_index = (year - 4) % 12 # dizhi = dizhi[dizhi_index] day柱子 = calendar[retindex] return f"{day柱子}"def divide_remainder(num, divisor): # 使用 divmod 方法获取整除结果和取余结果 result, remainder = divmod(num, divisor) if remainder: return result, remainder else: return resultdef get_time_column(year, month, day, birth): # 计算天干 tiangan = ["甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"] # 计算地支 dizhi = ["子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"] hour = None # if birth >= 100: hour = birth / 100 # else: # return if hour > 24: return # 时地支 时辰 = None if hour < 1: 时辰 = "子" hour_old = 1 elif hour < 3: 时辰 = "丑" hour_old = 2 elif hour < 5: 时辰 = "寅" hour_old = 3 elif hour < 7: 时辰 = "卯" hour_old = 4 elif hour < 9: 时辰 = "辰" hour_old = 5 elif hour < 11: 时辰 = "巳" hour_old = 6 elif hour < 13: 时辰 = "午" hour_old = 7 elif hour < 15: 时辰 = "未" hour_old = 8 elif hour < 17: 时辰 = "申" hour_old = 9 elif hour < 19: 时辰 = "酉" hour_old = 10 elif hour < 21: 时辰 = "戌" hour_old = 11 else: 时辰 = "亥" hour_old = 12 # print(时辰) # 时天干 day_tg = get_day_column(year, month, day, birth)[0] hour_tg = None if day_tg == '甲' or day_tg == '己': hour_index, yu = divide_remainder(hour_old, 10) if yu: hour_index = yu # print(hour_index) hour_tg = tiangan[hour_index - 1] if day_tg == '乙' or day_tg == '庚': hour_index, yu = divide_remainder(hour_old, 10) if yu: hour_index = yu hour_tg = ["丙", "丁", "戊", "己", "庚", "辛", "壬", "癸", "甲", "乙"][hour_index - 1] if day_tg == '丙' or day_tg == '辛': hour_index, yu = divide_remainder(hour_old, 10) if yu: hour_index = yu hour_tg = ["戊", "己", "庚", "辛", "壬", "癸", "甲", "乙", "丙", "丁"][hour_index - 1] if day_tg == '丁' or day_tg == '壬': hour_index, yu = divide_remainder(hour_old, 10) if yu: hour_index = yu hour_tg = ["庚", "辛", "壬", "癸", "甲", "乙", "丙", "丁", "戊", "己"][hour_index - 1] if day_tg == '戊' or day_tg == '癸': hour_index, yu = divide_remainder(hour_old, 10) if yu: hour_index = yu hour_tg = ["壬", "癸", "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛"][hour_index - 1] # 计算天干 tiangan_index = (year - 4) % 10 tiangan = tiangan[tiangan_index] # 计算地支 dizhi_index = (year - 4) % 12 dizhi = dizhi[dizhi_index] return f"{hour_tg}{时辰}"

In [84]:

print(get_bazi(1980,10,23,2230))庚申丙戌己巳乙亥

In [64]:

print(get_bazi(2011,4,12,1508))辛卯壬辰丁酉戊申

In [85]:

print(get_bazi(2024,1,1,0))癸卯甲子甲子甲子加入五行映射的算法

因为,四柱八字并没有体现出五行关系,于是晋级或说包装了一下,有了五行合格和五行缺失情况的输出。

In [93]:

def handlwuxingbybazhi(bz): print("八字:"+bz+"\n") ret1 = None tgls = {} tgls['甲']="阳木" tgls['乙']="阴木" tgls['丙']="阳火" tgls['丁']="阴火" tgls['戊']="阳土" tgls['己']="阴土" tgls['庚']="阳金" tgls['辛']="阴金" tgls['壬']="阳水" tgls['癸']="阴水" dzls = {} dzls['子']="阳水" dzls['丑']="阴土" dzls['寅']="阳木" dzls['卯']="阴水" dzls['辰']="阳土" dzls['巳']="阴火" dzls['午']="阳火" dzls['未']="阴土" dzls['申']="阳金" dzls['酉']="阴金" dzls['戌']="阳土" dzls['亥']="阴水" ret1 = tgls[bz[0]]+","+dzls[bz[1]]+","+tgls[bz[2]]+","+dzls[bz[3]]+","+tgls[bz[4]]+","+dzls[bz[5]]+","+tgls[bz[6]]+","+dzls[bz[7]] os = set() os.add(tgls[bz[0]][1]) os.add(dzls[bz[1]][1]) os.add(tgls[bz[2]][1]) os.add(dzls[bz[3]][1]) os.add(tgls[bz[4]][1]) os.add(dzls[bz[5]][1]) os.add(tgls[bz[6]][1]) os.add(dzls[bz[7]][1]) aa=["金","木","水","火","土"] for i in os: aa.remove(i) print("五行:"+tgls[bz[4]][1]+"命") print("五行缺:") print(aa) return f"{ret1}"

In [94]:

print(handlwuxingbybazhi(get_bazi(2017,2,6,1130)))八字:丁酉壬寅甲子庚午五行:木命五行缺:['土']阴火,阴金,阳水,阳木,阳木,阳水,阳金,阳火结语

有代码,有调用示例,欢迎大家评论交流。

道可道,就编码

0 阅读:0