[python] bit 操作与易经
从没有机会需要操作 bit,没想到写易经的程序非得用到不可。
第一个最需要的是,把数字转成 0101 的字符串。这个内建的 bin() 函数可用,只是它会在字符串前多加0b。依实际需要,得把 0b 去掉。
>>> bin(13)
'0b1100'
>>> bin(13)[2:]
'1101'
第二个就是把 0101 的字符串转回数字,这可以用 eval,或是 int('0b1100', 2) 来达成。
>>> int('0b1101',2)
13
>>> int('1101',2)
13
第三个,易经是 6-bits 系统,而且非常需要补 0 在高位数。
>>> bin(13)[2:].rjust(6,'0')
'001101'
第四个,因为我手上的易经参考书,低位写在前面,高位写在后面,我得把字符串反过来。从字符串转回数字也得一样照办。
>>> bin(13)[2:].rjust(6,'0')[::-1]
'101100'
>>> int('101100'[::-1], 2)
13
第五个,对某个 bit 做反转运算,因为对 6-bits 的操作没有把握再加上高低位已经反转,已经够乱了,所以采取直接对字符串操作,但因为 python 的字符串没法单独对第某个符操作,所以写了个函数代替。主要是拆开字符串为 list,操作完再组回去。index 从 0 开始。
def _invert_at(s, index):
ss = list(s)
if ss[index] == '0':
ss[index] = '1'
else:
ss[index] = '0'
return ''.join(ss)
>>> _invert_at('101100', 1)
'111100'
更新:经过研究测试之后,相同的功能可以用 bin(int(s, 2) ^ 2 (5 - index))[2:].rjust(6, '0') 来解决。
基础工程结束,接下来应用开始。因为用 bit 来表达了,原本常用的 1~8,都得用 0~7 这种以 0 开始的 index 系统。
一般卜卦是在得到一个卦(叫做“本卦”)之后,都会再求一个“变卦”及“互卦”。在一般简易数字型卜卦中,本卦、变卦、互卦的求法是:本卦是得到两个 0~7 之间的数字,一个代表上卦,一个代表下卦。例如,上卦 1、下卦 7,就是 101100,丰卦。(下卦在前面,低位在前面)
变卦是从 0~5 之间得到一个数字,代表动爻的位置,然后把本卦的对应的 bit 反转。例如,101100,我们得到 2 爻动,就是得到 111100,大壮卦。
互卦的求法是把本卦234爻做为下卦,把345爻做为上卦。011110,大过卦。
互卦用程序来表示很清楚:
>>> s = '101100'
>>> s[1:4] + s[2:5]
'011110'
接下来,用程序表示八宫卦象变化大概就是这样:
def get_8_change(s, step):
if step == 0:
return s
elif step == 1:
return _invert_at(s, 0)
elif step == 2:
return _invert_at(s, 1)
elif step == 3:
return _invert_at(s, 2)
elif step == 4:
return _invert_at(s, 3)
elif step == 5:
return _invert_at(s, 4)
elif step == 6:
return _invert_at(s, 3)
elif step == 7:
ss = _invert_at(s, 2)
ss = _invert_at(ss, 1)
ss = _invert_at(ss, 0)
return ss
拿坎宫的八个卦的程序是
s = '010010'
for i in range(8):
s = get_8_change(s, i)
print s, _int_from_bin_r(s), money64[s]
执行结果是:
010010 18 坎
110010 19 节
100010 17 屯
101010 21 既济
101110 29 革
101100 13 丰
101000 5 明夷
010000 2 师
八宫卦象变化的函数 get_8_change 的 step 0~6 跟京房 16 卦一样,可以做为基础继续改造。
分享