本文介绍生辰八字和八字五行的一种算法。站内有人在查询生辰八字的算法,此题本人也感兴趣。故以此文以续貂尾。
生辰八字计算要点是节气日,年柱以立春起,月柱以是月节气日起,故先要计算月首的节气日。本节气算法的节气时刻精度差些,但确定节气日是可以的。程序启动时先计算干支表和对应的五行表。具体的计算方法参阅程序的注释。算法很简单,一看就明白。要注意的是,八字的时柱先输出的是起时,生日时辰十二个时辰对应下面的起时表计算。程序列示文本打印输出和图片显示输出二种方法供参考。
本文主要介绍生辰八字的算法,没有计算农历日期,农历计算较为复杂,加农历算法,加月历打印输出成了万年历了。方法可参阅本站我的其他博文。
以下是计算方法的源码:
Canvas cs ;
string sBarDes[10]; //按钮
int nBarId[10];
float src[4]; //ClearDraw (cls) clear screen
int ds[3] ;
int i,j,t,k; //t = times
string fname; //filename 加底图
int sx, sy, x0, y0 ;
int alln,alln1;
int ns,leap;
double nleap,nleapd; //农历闰月,0无闰,闰月大小
int n,n0,n1,n2 ;
string s,s0,ss,s5,s6 ;
string s1,s2,s3,s4;
string s11, s12, s13, s14 ;
int wd ;
string wds,wdss; //weekday
double dy0,dy1,dm1,dd1;
int dy, dm, dd ;
string dy2, dm2, dd2 ; //日期输入dy2
double hh1,mm1,ss1;
string hh2,mm2,ss2;
int gzy,gzm,gzd,gzh; //干支 yy mm dd hh
string gzys,gzms,gzds,gzhs;
int gzn1;
int yz,mz; //年柱 月柱
string gzs, bzs ; //八字
string whss, g12ss,st28ss; //五行 十二建 二十八宿
string tgs, dzs, whs, whs1, whs2 ; //计算五行
int dzd0,dzd1; //冬至日
string jqnames ; //节气中文名称
string t1, t2, t3 ; //计算时间串 hh;mm;ss
double jd; //计算节气
double juD,tht,yrD;
double sD; //shouD
double vs,dalt; //solar
int jqdn ; //节气计算
int jqd1,jqd2 ;
string jqs1,jqs2;
string jqss1,jqss2;
string jnum,jname1, jname2 ;
main(){
setDisplay(1);
cs.SetBackground(240,240,240);
cs.Active();
sBarDes[0]="输入日期";
nBarId[0]=100;
sBarDes[1]=" ";
nBarId[1]=101;
sBarDes[2]="文本显示";
nBarId[2]=102;
sBarDes[3]="图片显示";
nBarId[3]=103;
sBarDes[4]="退出程序";
nBarId[4]=104;
sBarDes[5]="...";
nBarId[5]=105;
setToolBarHeight(6);
setButtonTextSize(14);
setToolBarBackgroundColor(255,220,220,220);
setButtonColor(255,240,240,240);
setButtonTextColor(255,0,0,120);
setToolBar(100,myToolBarProc,sBarDes,nBarId,6);
setTitle("生辰八字五行计算 ");
//**********
jqnames="小寒大寒立春雨水惊蛰春分清明谷雨立夏小满芒种夏至小暑大暑立秋处暑白露秋分寒露霜降立冬小雪大雪冬至";
wdss="星期日星期一星期二星期三星期四星期五星期六" ;
whss="海中金炉中火大林木路旁土剑锋金山头火洞下水城墙土白腊金杨柳木泉中水屋上土霹雷火松柏木长流水沙中金山下火平地木壁上土金箔金佛灯火天河水大驿土钗钏金桑松木大溪水沙中土天上火石榴木大海水";
g12ss="建除满平定执破危成收开闭";
st28ss="角亢氐房心尾箕斗牛女虚危室壁奎娄胃昴毕觜参井鬼柳星张翼轸";
setDisplay (0);
print " 请选择:输入日期 " ;
bzwh ( ) ; //八字五行计算
while (){}
}//main ()
bzwh ( ){ //八字干支表gzs五行表 whs
int n1,n2 ;
tgs="甲乙丙丁戊己庚辛壬癸" ;
dzs="子丑寅卯辰巳午未申酉戌亥" ;
whs1="木木火火土土金金水水" ;
whs2="水土木木土火火土金金土水" ;
setDisplay (0);
for (i=0; i<60; i++){
n1=i-i/10*10 ; n2=i-i/12*12 ;
s1=subString (tgs, n1, 1) ;
s2=subString (dzs, n2, 1) ;
s3=subString (whs1, n1, 1) ;
s4=subString (whs2, n2, 1) ;
gzs=gzs+s1+s2 ; //建八字表
whs=whs+s3+s4 ; } //建五行表
}//bzwh ()
test (){ // 生辰八字计算,测试
cs.ClearDraw (0,src); //清屏
clearOutput () ;
cs.SetTextSize (30);
cs.SetColor (255,0,0,150) ;
fname="/storage/emulated/0/tutu.jpg";
cs.DrawBitmap(fname,0,2); //加底图
sx=60 ; sy=100 ;
ss="InputDate = "+dy2+"-"+dm2+"-"+dd2;
cs.DrawText (ss, sx, sy-60);
print ss ;
ss= "是日为:"+wds ;
print ss ;
cs.DrawText (ss, sx, sy-30);
print " " ;
print "all days = ",alln," ",alln1;
// 计算节气日,年柱以立春日起算
// 计算节气日,月柱以月节气日起算
//**** calculate solarterm //show 节气
dy2=intToString(dy); //show 节气
dm2=intToString(dm);
dy1=stringToDouble(dy2);
dm1=stringToDouble(dm2);
dy0=dy1;
n=dm*2-1;
caljq(); //节气计算
jqd1=(int)(dd1);
jqs1=subString(jname2,0,2);
cs.DrawText (jname2,sx,sy+20);
jqss1=jname2;
n=dm*2;
caljq (); //节气计算
jqd2=(int)(dd1);
jqs2=subString(jname2,0,2);
cs.DrawText(jname2,sx,sy+50);
jqss2=jname2;
print jqss1 ;
print jqss2 ;
//calculate GZ,gzy,gzm,gzd,alln
ss= "节气日 : " +intToString(jqd1) ;
print ss ;
cs.DrawText(ss, sx, sy+90);
print " " ;
print " " ;
ss= "八字五行计算如下:" ;
print ss ;
print " " ;
cs.DrawText(ss, sx, sy+150);
//计算天数,dy+2096,算公元前避免出现负数
alln1=alln1+dd-1; //all days
n=(dy+2096);
if(dm<2)n=n-1;
if(dm==2&&dd<jqd1)n=n-1;
gzy=n-(int)(n/60*60);
s1=subString(gzs,gzy*2,2); //年柱
if(dd<jqd1){mz=1;}else{mz=0;}
gzn1=(dy+2096)*12+dm-mz;
gzm=gzn1-(int)(gzn1/60*60);
s2=subString (gzs,gzm*2,2); //月柱
n1=alln1+9;
gzd=n1-(int)(n1/60*60);
s3=subString(gzs,gzd*2,2); //日柱
gzh=(gzd-(int)(gzd/5*5))*12;
s4=subString(gzs,gzh*2,2); //时柱
dd2=intToString(dd); //this day $
if(len(dd2)==1)dd2="0"+dd2; //format
s="日期:"+dy2+" 年 "+dm2+" 月 "+dd2+ " 日";
//cs.SetTextSize (27);
cs.DrawText(s,sx, sy+200);
print s ;
bzs="八字:"+s1+" "+s2+" "+s3+" "+s4;
cs.DrawText(bzs,sx , sy+230);
print bzs ;
string wh ;
s11=subString (whs,gzy*2,2);
s12=subString (whs,gzm*2,2);
s13=subString (whs,gzd*2,2);
s14=subString (whs,gzh*2,2);
wh=s11+" "+s12+" "+s13+" "+s14 ;
wh="五行:"+wh ;
cs.DrawText(wh, sx, sy+260); //output
print wh ;
print " " ;
//八字五行十二建二十八宿
s=" " ; ss=" " ;
s11=subString (whss,(gzy/2)*3,3);
s12=subString (whss,(gzm/2)*3,3);
s13=subString (whss,(gzd/2)*3,3);
s14=subString (whss,(gzh/2)*3,3);
s="年 : "+s1+s11; //show 五行
cs.DrawText (s,sx, sy+320);
print "年: "+s1+s11 ;
s="月 : "+s2+s12;
cs.DrawText (s, sx, sy+350);
print "月: "+s2+s12 ;
n=alln1+3; //print 二十八宿
n1=n-n/28*28;
s5=subString (st28ss,n1,1);
cs.DrawText (ss, sx+190, sy+380);
n=alln1-(dy-1900)*12-dm+10; // 12建日
if (dd>=jqd1)n=n-1;
n1=n-n/12*12;
s6=s5+subString(g12ss,n1,1);
cs.DrawText (s6, sx+200, sy+380);
s="日 : "+s3+s13 ;
cs.DrawText (s, sx, sy+380);
print "日: "+s3+s13+s6 ;
s="时 : "+s4+s14;
cs.DrawText (s, sx, sy+410);
print "时: "+s4+s14 ;
//** 八字起时 ,十二时辰对照表 *************
x0=60;
y0=600;
cs.SetTextSize(24);
s="起时 : ";
cs.DrawText(s,x0,y0-30);
s="23 - 1 11 - 13";
cs.DrawText(s,x0,y0-5);
s=" 1 - 3 13 - 15";
cs.DrawText(s,x0,y0+20);
s=" 3 - 5 15 - 17";
cs.DrawText(s,x0,y0+45);
s=" 5 - 7 17 - 19";
cs.DrawText(s,x0,y0+70);
s=" 7 - 9 19 - 21";
cs.DrawText(s,x0,y0+95);
s=" 9 - 11 21 - 23";
cs.DrawText(s,x0,y0+120);
for(i=0;i<6;i++){
s5=subString(gzs,(gzh+i)*2,2);
s6=subString(gzs,(gzh+6+i)*2,2);
s=s5+" "+s6;
cs.DrawText(s,x0+80,y0-5+i*25); }
string wh1, wh2, h1, h2 ;
wh1=" "; wh2=" "; h1=" "; h2=" ";
n=gzh ;
for(i=n ; i<n+6; i++){
whs1=subString (whs, i*2, 2) ;
whs2=subString (whs, (i+6)*2, 2) ;
wh1=wh1+whs1+" " ;
wh2=wh2+whs2+" " ;
s5=subString(gzs, i*2,2);
s6=subString(gzs, (i+6)*2,2);
h1=h1+s5+" " ;
h2=h2+s6+" " ; }
wh1="23 - 11 "+wh1 ;
wh2="11 - 23 "+wh2 ;
cs.SetTextSize (24);
print " " ;
print "起时:" ;
cs.DrawText (wh1,50,760) ;
cs.DrawText (wh2,50,790) ;
print " " ;
print "23 - 11 ", h1 ;
print wh1 ;
print " " ;
print "11 - 23 ", h2 ;
print wh2 ;
cs.Update () ;
}//test ( )
inputDate (){ //输入日期
string sDat[101];
getDate(ds); //getDate = today
pickDate("输入日期:",ds); //input date
dy=ds[0];
dm=ds[1];
dd=ds[2];
dy2=intToString(dy); //this year
dm2=intToString(dm); //this month
if (dm<10) dm2="0"+dm2 ;
dd2=intToString(dd); //this day
if (dd<10) dd2="0"+dd2 ;
//print "InputDate = ",dy2+"-",dm2+"-"+dd2;
getWeekday () ;
}//inputDate()
getWeekday () {
//传人dy dm dd , 输出星期wds , 天数alln1
//计算月首日星期几 alln=... +1+1 ;
//计算当日或输入 是日 alln=... +1+dd ;
int ty, tm ;
ty=dy;
tm=dm;
if (dm<3){
ty=dy-1;
tm=dm+12; }
//first day=1 this month
//iWeek=(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)
//mod 7 基姆拉尔森公式
alln=2*tm+3*(tm+1)/5+ty+(int)(ty/4);
alln=alln-(int)(ty/100)+(int)(ty/400)+1+dd;
wd=alln-alln/7*7; //mod (alln,7)
wds=subString(wdss,wd*3,3);
string yds; //计算天数
string ydds;
double tms;
yds="000031059090120151181212243273304334";
ydds=subString(yds,(dm-1)*3,3);
tms=stringToDouble(ydds);
alln1=(dy-1900)*365+((dy-1900-1)/4)+(int)(tms)+1;
if ((dy-dy/4*4)==0&&dm>2)alln1=alln1+1;
// return weekday = wds , alln1
test () ;
}//getWeekday ()
myToolBarProc(int nBtn,int nContext){
if(nBtn==100){//input date
setDisplay (0);
inputDate ( ) ;
}
if(nBtn==101){//test input
inputDate ( ) ;
}
if(nBtn==102){//关闭图板文本打印输出
setDisplay (0);
}
if(nBtn==103){//显示图板
setDisplay (1);
}
if(nBtn==104){//退出程序
clearOutput();
cs.ClearDraw (0,src);
setDisplay (0);
exit (0);
}
if(nBtn==105){//@testdraw
setDisplay (1);
}
}//myToolBar ()
caljq(){//calculate solar ** return jname2
//传入dy0, n节气序数,输出节气时间
juD=dy0*(365.2423112-0.000000000000064
*(dy0-100)*(dy0-100)- 0.00000003047
*(dy0-100))+15.218427*n+1721050.71301;
tht=0.0003*dy0-0.372781384-0.2617913325*n;
yrD=(1.945*sin(tht)-0.01206*sin(2*tht))
*(1.048994-0.00002583 *dy0);
sD=-0.0018*sin(2.313908653*dy0
-0.439822951-3.0443*n);
//'vs = juD '** 平气
vs = (juD + yrD + sD); // '** 定气
dalt=-15+(juD-2382148)*(juD-2382148)/41048480;
//print dalt;
dalt = dalt/86400;
//print dalt;
jd = vs - 0.5 - dalt-0.025;
int gg;
gg=n-(int)(n/2*2);
jdtoGD ();
jqs1=subString (jqnames,(n-1)*2,2);
//print "jqs1 = ",jqs1;
s=jqs1+" " +jname2;
//print jname2;
}//caljq() ****************************
//calculate jd to GD ** return jname2 *****
jdtoGD(){
double a,b,c,d,e;
double F;
double allss;
F=jd-(int)(jd);
//print " ";
//print " JD = ",jd;
//print " 时分秒 日小数 = ",F;
a=(int)(jd+0.5);
b=a+1537;
c=(int)((b-122.1)/365.25);
d=(int)(365.25*c);
e=(int)((b-d)/30.6001);
dd1=b-d-(int)(30.6001*e);
dm1=e-1-(int)((e/14)*12);
dy1=c-4715-(int)((7+dm1)/10);
//print a," ",b," ",c," ",d," ",e;
dy2=intToString (dy);
dm2=intToString (dm);
dd2=doubleToString (dd1);
if (len(dm2)==1)dm2="0"+dm2;
if (dd1<10)dd2="0"+dd2;
dd2=subString (dd2,0,2);
//print dy2+" 年 "+dm2+" 月 "+dd2+" 日 ";
if(n==24)jqdn=(int)(dd1);
if (n==24&&dm1<3)jqdn=jqdn+1;
//日allss 的小数转为时分秒
allss=(int)((jd-a)*86400+43200.5);
//print "allss = ", allss;
hh1=(int)(allss/3600);
mm1=(int)((allss-hh1*3600)/60);
ss1=(int)(allss-hh1*3600-mm1*60);
if(ss1>=60){
ss1=ss1-60;
mm1=mm1+1;}
if(mm1>=60){
mm1=mm1-60;
hh1=hh1+1;}
//print "JD 转为 GD,计算结果:”;
hh2=doubleToString(hh1);
mm2=doubleToString(mm1);
ss2=doubleToString(ss1);
if(hh1<10){
hh2="0"+doubleToString(hh1);}
if(mm1<10){
mm2="0"+doubleToString(mm1);}
if(ss1<10){
ss2="0"+doubleToString(ss1);}
hh2=subString (hh2,0,2);
mm2=subString (mm2,0,2);
ss2=subString (ss2,0,2);
jname1=subString(jqnames,(n-1)*2,2);
//print "节气 : ",jname1;
jname2=jname1+": "+dm2+"-"+dd2+" "+hh2+":"+mm2+":"+ss2;
//return jname2;
}//jdtoGD() **************
//**** END ****