2013年11月16日 星期六

[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 卦一樣,可以做為基礎繼續改造。

沒有留言:

張貼留言