古人以筮草为占卜工具,以一定的规则进行计算,从而得到卦象。
铜钱起卦发明之前,筮草占法一直是主流,并且占卜之前还要沐浴更衣等走完一整套流程,仪式感满满。
经朋友提醒,我将在自己的排盘软件中增加“大衍筮法”。
可大衍筮法该如何用软件实现呢?
《周易·系辞》中记载了古人的这种占问规则,这是明朝之前所有典籍中唯一记载的占问规则。原文具体如下:
大衍之数五十,其用四十有九。分而为二以象两,挂一以象三,揲之以四以象四时,归奇于扐以象闰,五岁再闰,故再扐而后挂。天数五,地数五,五位相得而各有合。天数二十有五,地数三十,凡天地之数五十有五。此所以成变化而行鬼神也。《乾》之策二百一十有六,《坤》之策百四十有四,凡三百有六十,当期之日。二篇之策,万有一千五百二十,当万物之数也。是故四营而成《易》,十有八变而成卦,八卦而小成。
由于没有其他同类的规则,所以原文中也未曾对此方式进行取名。
后世都称它为“大衍筮法”。本文亦取此名。
朱熹在他的《周易本义》中,对大衍筮法进行了详细的描述:
命之曰:“假尔泰筮有常,假尔泰筮有常。某官姓名,今以某事云云,未知可否。爰质所疑于神于灵,吉凶得失,悔吝忧虞,惟尔有神,尚明告之。”乃以右手取一策,反于椟中,而以左右手中分四十九策,置格之左右两大刻。
此第一营,所谓分而为二以象两者也。
次以左手取左大刻之策执之,而以右手取右大刻之一策,挂于左手之小指间。
此第二营,所谓挂一以象三者也。
次以右手四揲左手之策。揲,食列反。
此第三营之半,所谓揲之以四,以象四时者也。
次归其所余之策,或一、或二、或三、或四,而扐之左手无名指间。
此第四营之半,所谓归奇于扐,以象闰者也。
次以右手反过揲之策于左大刻,遂取右大刻之策执之,而以左手四揲之。
此第三营之半。
次归其所余之策如前,而扐之左手中指之间。
此第四营之半,所谓再扐以象再闰者也。
一变所余之策,左一则右必三,左二则右亦二,左三则右必一,左四则右亦四。通挂一之策,不五则九。五以一其四而为奇,九以两其四而为偶,奇者三而偶者一也。
次以右手反过揲之策于右大刻,而合左手一挂二扐之策,置于格上第一小刻。
以东为上,后放此。
是为一变。再以两手取左右大刻之蓍合之。
或四十四策或四十策。
复四营如第一变之仪,而置其挂扐之策于格上第二小刻,是为二变。复,扶又反。营,于平反,下同。
二变所余之策,左一则在必二,左二则右必一,左三则右必四,左四则右必三。通挂一之策,不四则八。四以一其四而为奇,八以两其四而为偶,奇偶各得四之二焉。
又再取左右大刻之蓍合之。
或四十策,或三十六策,或三十二策。
复四营如第二变之仪,而置其挂扐之策于格上第三小刻,是为三变。
三变余策,与二变同。
三变既毕,乃视其三变所得挂扐过揲之策,而画其爻于版。
挂扐之数,五四为奇,九八为偶。挂扐三奇,合十三策,则过揲三十六策而为老阳,其书为“〇”,所谓重也。挂扐两奇一耦合十七策,则过揲三十二策而为少阴,其画为“- -”,所谓拆也。挂扐两耦一奇,合二十一策,则过揲二十八策而为少阳,其画为“—”,所谓单也。挂扐三耦合二十五策,则过揲二十四策,而为老阴,其书为“×”,所谓交也。
如是每三变而成爻。
这段文字有点繁杂。按照其描述,我将此规则用通俗语言给描述出来,具体为:
1.从50根筮草中拿出一根代表太极,把剩余的49根分成左右两部分;
2.取出右边一根挂于左手,把左部分筮草以4取余数,余数挂于左手;
3.把右部分筮草以4取余数,余数挂于左手;
4.再将挂在左手的所有筮草放一边,把左右两部分筮草合在一起,再分成左右两部分;
5.同样的取出右边一根挂于左手,左部分以4取余挂于左手、右部分以4取余挂于左手。将左手所挂全部放一边,把左右两部分筮草合在一起,再分成左右两部分;
6.同样的步骤再来一次;
7.查询剩下的两部分筮草之和,以4取商,9为老阳,8为少阴,7为少阳,6为老阴;
8.按照同样的方式再操作5次,形成最终六个爻。
按照这个流程,我写出了如下算法(以ASP语言为例):
vs="" '初始化卦爻值,相当于“硬币背数”
for dy1=1 to 6 '相当于起卦次数
sc=50 '筮草数量为50
sc=sc-1 '完全按照大衍筮法的规则,取出一根象征太极,剩余49
for dy2=1 to 3
randomize
sc1=int((sc-2)*rnd()+2) '左手拿到的一堆,取值范围[2,sc-1]
sc2=sc-sc1 '这里是右手里的一堆
sc1=sc1-1 '左手里的拿出一根
sc11=sc1 mod 4 '取左手数量的余数
if sc11=0 then sc11=4 '如果没有余数则将余数设置为4
sc1=sc1-sc11 '丢掉余数
sc22=sc2 mod 4 '取右手数量的余数
if sc22=0 then sc22=4 '如果没有余数则将余数设置为4
sc2=sc2-sc22 '丢掉余数
sc=sc1+sc2
next
dy=sc/4
select case dy
case 6
vs=vs&"0"
case 7
vs=vs&"1"
case 8
vs=vs&"2"
case 9
vs=vs&"3"
end select
next
运行了几次,发现老阴的比例特别低,老阳的比例又异常偏高。
于是我把这段程序运行了100万次(不要怀疑,这对程序员来讲太过于简单),得到的结果为(老阴/少阳/少阴/老阳):
53006 / 285319 / 452224 / 209415
也就是大约:1 / 5.38 / 8.53 / 3.95
这个比例,也就是大衍筮法算法的成卦比例。
而我认为:正常的概率应该是接近于1/3/3/1才对,这才跟目前主流的、被公认为准确的硬币起卦方式相匹配。
肯定是哪里出了问题。那就找问题呗,还有啥事能难得倒我龙甲的?
起初我是怀疑《周易·系辞》里的表述有问题。我的怀疑是有理由的:
大衍之数五十,这个“五十”是怎么得来的?《易》原文里面没有,《系辞》上文也没有,那凭什么就得到了这个“五十”的大衍之数呢?
与这段文字在一起的还有这么一段文字:
天一地二,天三地四,天五地六,天七地八,天九地十。天数五地数五,五位相得而各有合。天数二十有五,地数三十,凡天地之数,五十有五,此所以成变化而行鬼神也。
这段文字就紧邻在“大衍之数五十”的前面。由此,我认为“大衍之数五十”应当是“大衍之数五十有五”才对。
假设我的猜测是对的,那么我就把这个55放进我的程序算法里,也就是把第三行改成这样写:
sc=55 '筮草数量改为55
进行了几轮60000次的起筮,运行的结果如下:
0 / 0 / 13558 / 30051
0 / 0 / 13616 / 29967
0 / 0 / 13577 / 30005
0 / 0 / 13546 / 29961
很遗憾,老阴和少阳根本就没有出现,而少阴/老阳的比例接近于9/20,这个准确度还不如原来的结果。
我又对太极之数进行了修改,也就是从55根筮草中拿出不用的、相当于太极的筮草的数量,由1逐步上调到9,发现结果都不尽如人意。
(对结果感兴趣的朋友可以自己用程序尝试)
也就是说,要么我对“大衍之数五十”的质疑是有问题的,要么说就算大衍之数就是我认为的55,也无法得到更加完美的结果来。
很显然,我还是不要质疑了。接受“大衍之数五十”就行啦。
古人就是古人,不得不服。
那我就换个方向来思考:程序是不是有问题?
经过重新检视,发现有一行代码是存疑的,就是第七行:
sc1=int((sc-2)*rnd()+2)
这一行代码代表的意思就是把筮草分成两堆,每堆至少两根,至多……那就是总数减去两根,因为另外一堆也至少要有两根。
这里是不符合人的正常操作的。因为一般人都会把两堆筮草分得大致相当,很少有人故意拣出两三根当作一堆的。
也就是说,任意一堆的数量,应当符合正态分布:
其中作为比例的x=0时,也就是第一堆筮草的数量应当接近于一半,只有接近于一半的数量,其概率才是最大的。
这个是标准正态分布函数。
不容易看懂?没关系,这是高等数学知识,没必要看懂。你只需要明白:平分的概率最大、数量差别越大的概率越小,就基本明白了正态分布的概念。
现在涉及到一个如何获取结果的问题。
最简单的思路也就是:先由系统生成一个随机数n1,然后按照这个随机数所在的位置再生成一个随机数n2来判断它出现的概率有多大,如果n2在曲线上方,则果断丢弃n1,并且重新生成n1再来继续;如果n2在曲线下方,则接受n1。再根据这个n1值来算出第一堆的数量来。
那么,这就存在一个系统锁死的可能:如果n2一直都在曲线的上方,则程序执行时间将会无限延长。显然这不是一个合理的算法。
那么,就使用加权形式,增加随机数n1居中的权重。随着n1偏离中心位置,其权重逐步降低。
这样便可以一次性生成随机数,然后根据该随机数的权重来找到其应在的位置,进而求到其余数。
于是,得到更新后的算法:
(核心算法不宜公开,故此文省略)
经过反复测试,得到了这样的结果(以下每组运行20万次):
11899 / 60375 / 88511 / 39215
11918 / 60433 / 88613 / 39036
12034 / 60086 / 88626 / 39254
11767 / 60449 / 88559 / 39225
11976 / 60097 / 88868 / 39059
合计100万次的结果就是:
59594 / 301440 / 443177 / 195789
也就是大约:1 / 5 / 7.43 / 3.29
仍然跟理想模型1/3/3/1有较大差距。
还有错误。
可是,错误在哪里呢?
算法已经近乎完美,难道还有需要改进的地方吗?
那么,我就再换个思路:
为何1/3/3/1是理想状态?
因为摇硬币的时候,老阴/少阳/少阴/老阳的比例就是如此。
比如三枚硬币,分别是a、b、c,其中1为阳、0为阴,那么它们的组合情况共有以下几种:
a1-b1-c1(老阳)
a1-b1-c0(少阴)
a1-b0-c1(少阴)
a1-b0-c0(少阳)
a0-b1-c1(少阴)
a0-b1-c0(少阳)
a0-b0-c1(少阳)
a0-b0-c0(老阴)
由于硬币的阴阳两面出现的概率基本相等,所以这8种组合就是各占1/8的概率,从而得到老阴/少阳/少阴/老阳的比例就是1/3/3/1。
这个思路,是建立在“硬币起卦方式为标准方式”这一命题的基础之上。
那么,作为参照的硬币起卦方式就是正确的吗?
未必吧?
好像是先有的大衍筮法,后来才有的硬币起卦方式。
并且,大衍筮法的具体规则是朱熹最早记录下来的,而硬币起卦又是谁提出来的?
所以,使用硬币起卦的标准概率来衡量大衍筮法的正确与否,好像太不合适了点。
那么,我就从大衍筮法的每个步骤进行分析,对大衍筮法结果应有的概率进行计算。
第一次拆分,50根筮草,取出一根,剩下49根。然后将剩余的49根筮草拆分成两部分,再在一组中取出一根,然后以四来取余数,那么余数有四种可能,分别是1、2、3、4,在这里分别使用a1、b1、c1、d1来代替。另外一组的余数肯定就分别是3、2、1、4。那么a1、b1、c1均留下44根,d1留下40根,a1、b1、c1、d1四种情况的概率相等;
第二次拆分,第一组取出了一根,余数依然是1、2、3、4这四种可能,用a2、b2、c2、d2来代表,第二组的余数应该是2、1、4、3,这样的话,a2、b2应当在原筮草数量的基础上减少4根,而c2、d2则在原筮草数量的基础上减少8根;
第三次拆分,跟第二次类似,四种情况分