バイオリオズムの計算

 バイオリズムという言葉を良く聞くので,その計算プログラムを作ろうと考え,少し調べてみました。


 バイオリズムは「生命の活動は一定の周期によって行われている」という考え方に基づいています。 20世紀はじめ,何人かの医師による臨床的考察で得られた学説だそうです。それによると人間の生命としての基本要素として,身体,感情,知性を取り上げ,それぞれ

身体(physical)のリズムが23日周期,

感情(sensitivity)のリズムが28日周期,

知性(intellectual)のリズムが33日周期

の周期を持つとのことです。それぞれの頭文字を取って,PSI学説とも言われます。

 このリズムによって人間の生命活動が行われているので,このリズムでの高低を知ることで日常生活の参考にしようという考えです。


 この学説の当否について,私は意見を述べる資格はありません。しかし,その計算結果をグラフにしたものを良く見かけますし,実際それを表示するソフトが市販されていたりします。

 そこで,これを Tiny Basic のプログラムとして,実現してみることにしました。

 実は,上の様な原理の説明は良くあるのですが,実際にどのように計算をしてグラフ化しているのか説明をしているホームページは余りありません。それでもいくつかのホームページのその方法が載っていました。

 それによると,生まれた日からその周期が始まるとして,現在までそれを忠実に計算しているだけのようです。そうだとすると,問題は,生まれた日からの日にちを計算できれば良いことになります。これが求まればプログラムは簡単に作成できます。

 そこで以下に,このプログラムの作成を考えます。

生まれた日からある年のある日までの日数を求める

 この計算は,バイオリズムの計算を別にしても,興味がある問題です。

 まず,この計算は次の2つことが出来れば良いことはすぐに分かります。

  1. y年の1年の日数

  2. y年m月d日に対して,y年1月1日からの日数

  3. y年m月d日に対して,m月d日から12月31日までの日数

 2,3の計算はすべて数えで行います。つまり,当日も1日とします。


1.y年の1年の日数

 この計算は閏年が分かれば良いだけですが, Tiny Basic では閏年を判定する関数 IsLeapYear がありますから,これは簡単です。

 関数の形でこれを書いてみると次で与えられます。

Function DaysOfYear(Y)
  If IsLeapYear(Y) then
     DaysOfYear = 366
  Else
     DaysOfYear = 365
  End if
End Function

簡単ですね。


2.y年m月d日に対して,y年1月1日からの日数

 この計算も,原理的には簡単です。m-1月までの月の日数とnを加えれば求められます。月ごとに日数は違いますから,この計算ではそれを配列変数等に入れておく必要があります。

12個の配列変数Month(i) を用意してそれに各月の日数を入れておきます。この入れ方はいく通りか考えられますが,ここでは,

M$="312831303130313130313031"

という文字列に,月のデータを入れておいて,それを Month(i) に読み込ませることにします。閏年の場合は2月だけ変更します。

 このようにして,その年の各月の日数が決れば,1月1日からの日数は前月迄の日数を加えて,その日にちを加えれば得られます。

 これも関数の形で書くと次のようになります。

Function DaysFromNYDay(Y,M,D)
   Dim Month(12)
   M$="312831303130313130313031"
   For i=1 to 12 
      Month(i) = Val(Mid$(M$,2*i-1,2))
   Next i
   If IsLeapYear(y) then Month(2)=29
   Ds = 0
   For i=1 to M-1
      Ds = Ds + Month(i)
   Next i
   DaysFromNYDay = Ds + D
End Function

 この関数は例えば,

Print DaysFromNYDay(2001,7,7)

とすると,2001年1月1日から2001年7月7日迄の日数を表示します。


3.y年m月d日に対して,m月d日から12月31日までの日数

 これは上の関数DaysofYear(Y)とDayFromNYDay(Y,M,D)を使えば簡単にできます。

DaysOfYear(Y) - DaysFromNyDay(y,m,d) + 1

で与えられます。


 そこでこれらの関数を使って,誕生日 BY年BM月BD日から,Ye年Mo月Da日迄の日数を計算することを考えます。ここで,BY ≦Ye とします。

BY = Ye の場合と,BY < Ye の場合に分けます。

BY = Ye の場合は,誕生日BM月BD日からから,Mo月Da日の日数は両方の1月1日からの日数を数えてその差を取ることで得られます。即ち,

DaysFromNYDay(Ye,Mo,Da) - DaysFromNYDay(Y,M,D) + 1

で与えられます。最後に +1 とするのは,「数え」で考えることからです。

BY < Ye の場合は,BY年とYe年,その間の年に分けて考えます。

(1)BY 年では,誕生日BM月BD日から12月31日迄の日数を計算します。これは,

DaysOfYear(BY) - DaysFromNYDay(BY,BM,BD) + 1

で与えられます。

(2)BY年とYe年との間のi年の日数は,

DaysOfYear(BY)

で与えられます。

(3)Ye年ではMo月Da日までの日数は

DaysFromNYDay(BY,BM,BD)

で与えられます。

 以上のことを併せて,BY年BM月BD日から,Ye年Mo月Da日迄の日数を与える関数DaysFromBirthは次のように書けます。

Function DaysFromBirth(BY,BM,BD,Ye,Mo,Da)
   If Ye > BY then
      Days = 365 - DaysFromNYDay(BY,BM,BD) + 1
      If IsLeapYear(BY) then Days = Days + 1
      For i=BY+1 to Ye-1
         If IsLeapYear(i) then
            Days = Days + 366
         Else
            Days = Days + 365
         End if
      Next i
      DaysFromBirth = Days + DaysFromNYDay(Ye,Mo,Da)
   Else 
      DaysFromBirth = DaysFromNYDay(Ye,Mo,Da) - DaysFromNYDay(Y,M,D) + 1
   End if
End Function

ここでは,DaysOfYearを使わないでそのコードを中に書いています。 

生まれた日から今日までの日数を求める

 関数DaysFromBirthが出来れば,今日までの日数を求めるのは簡単です。それは今日の日付を上の Ye年Mo月Da日に入れて計算をすれば良いだけだからです。今日の日付を求めるのは Date$ 関数を使えば簡単に出来ます。Date$ 関数は"YYYY/MM/DD"の形の文字列として与えられますから,

Ye = Val(Mid$(Date$,1,4))
Mo = Val(Mid$(Date$,6,2))
Da = Val(Mid$(Date$,9,2))

とすれば求めるものが得られます。

これらを纏めて,生まれた日から今日までの日数を求めるプログラムを書くと次のようになります。


'--------------------------------------
' 誕生日からの日数の計算
'  DaysFromBirth.tbt
'  Ver. 0.2 by T.Takeuchi
'  2004/9/13
'--------------------------------------
 Title$="誕生日からの日数"
 MSG$="生年月日を" & Chr$(13) & Chr$(10) _
      & "1980,7,10" & Chr$(13) & Chr$(10) _
      & "のようにカンマで区切って入力して下さい。"
 In$ = InputBox(MSG$,Title$,"1980,7,10")
 BY=Val(Split$(In$,","))
 BM=Val(Split$(In$,","))
 BD=Val(In$)

 Ye = Val(Mid$(Date$,1,4)):?Ye
 Mo = Val(Mid$(Date$,6,2)):?Mo
 Da = Val(Mid$(Date$,9,2)):?Da

 Print "今日は誕生日から";DaysFromBirth(BY,BM,BD,Ye,Mo,Da);"日目です。"
 End


Function DaysFromBirth(Y,M,D,Ye,Mo,Da)
   If Ye > Y then
      Days = 365 - DaysFromNYDay(Y,M,D) + 1
      If IsLeapYear(Y) then Days = Days + 1
      For i=Y+1 to Ye-1
         If IsLeapYear(i) then
            Days = Days + 366
         Else
            Days = Days + 365
         End if
      Next i
      DaysFromBirth = Days + DaysFromNYDay(Ye,Mo,Da)
   Else 
      DaysFromBirth = DaysFromNYDay(Ye,Mo,Da) - DaysFromNYDay(Y,M,D) + 1
   End if
End Function


Function DaysFromNYDay(Y,M,D)
   Dim Month(12)
   M$="312831303130313130313031"
   For i=1 to 12 
      Month(i) = Val(Mid$(M$,2*i-1,2))
   Next i
   If IsLeapYear(y) then Month(2)=29
   Ds = 0
   For i=1 to M-1
      Ds = Ds + Month(i)
   Next i
   DaysFromNYDay = Ds + D
End Function

 

バイオリズムの計算

 誕生日からの日数をDとすると,身体,感情,知性のバイオリズムはそれぞれ,23日,28日,33日の周期を持ちますから,それを周期とした Sinカーブをそれぞれのバイオリズムとします。ですからそれぞれの値は,

Sin(D*2*Pi/23)
Sin(D*2*Pi/28)
Sin(D*2*Pi/33)

で与えられます。バイオリズムの表は1ヶ月単位で表すとするすると,月の初めから,月の終わりまでの値をそれぞれ計算して,その値を線で結んだグラフを描きます。それぞれの曲線の描き方は,周期が違うだけですから,周期mに対してそれを描く Sub プログラムを書くことにします。


 これは次のようになります。

Sub DrawBioCurve(BY,BM,BD,TY,TM,m)
 For i=0 to Month(TM)-1
   x1 = i 
   y1 = Sin((DaysFromBirth(BY,BM,BD,TY,TM,x1)/m)*2*Pi) 
   x2 = i+1
   y2 = Sin((DaysFromBirth(BY,BM,BD,TY,TM,x2)/m)*2*Pi)
   Line (x1,y1)-(x2,y2)
 Next i
End Sub

 このプログラムは生年月日 BY年BM月BD日の人のTY年TM月のバイオリズムのグラフを描きます。ここでm=23のとき,身体,m=28のとき,感情,m=33のとき,知性のグラフになります。


以上を纏めて,1つのプログラムにしたものが次です。


'--------------------------------------
' バイオリズム Biorhythm.tbt
'   Ver. 0.2 by T.Takeuchi
'   2003/11/1
'--------------------------------------
' 月の設定
'--------------------------------------
 Public Month(12)
 M$="312831303130313130313031"
 For i=1 to 12 
    Month(i) = Val(Mid$(M$,2*i-1,2))
 Next i

'--------------------------------------
' 入力
'--------------------------------------
 Title$="バイオリズムの計算"
 MSG$="生年月日を" & Chr$(13) & Chr$(10) _
      & "1980,7,10" & Chr$(13) & Chr$(10) _
      & "のようにカンマで区切って入力して下さい。"
 In$ = InputBox(MSG$,Title$,"1980,7,10")
 BY=Val(Split$(In$,","))
 BM=Val(Split$(In$,","))
 BD=Val(In$)
 MSG$="表示月を" & Chr$(13) & Chr$(10) _
      & "2003,11" & Chr$(13) & Chr$(10) _
      & "のようにカンマで区切って入力して下さい。"
 IV$ = Str$(ThisYear) & "," & Str$(ThisMonth)
 In$ = InputBox(MSG$,Title$,IV$)
 TY=Val(Split$(In$,","))
 TM=Val(Split$(In$,","))

'--------------------------------------
' 計算
'--------------------------------------
 BackColor = "#DDFFDD"
 GScreen(600,300)
 Window (0,-1.5)-(31,2)
 MathGraph On
 PrintGTitle "バイオリズムの計算"
 ForeColor = "Cyan"
 Line (0,0)-(31,0)
 GLocate(2,1.8)
 ForeColor = "Navy"
 P$="生年月日:"+Str$(BY)+"年"+Str$(BM)+"月"+Str$(BD)+"日"
 GPrint P$
 GLocate(17,1.8)
 P$="表示年月:"+Str$(TY)+"年"+Str$(TM)+"月"
 GPrint P$
 GFontSize = 7
 For i=1 to Month(TM)
    GLocate(i-1,-0.02): D$=Str$(i)
    GPrint D$
 Next i
'--------------------------------------

 DrawWidth = 2
 ForeColor = "Black"
 Line (1,-1.2)-(3,-1.2)
 GLocate (4,-1.1)
 GPrint "身体"
 Call DrawBioCurve(BY,BM,BD,TY,TM,23)

'--------------------------------------
 ForeColor = "Red"
 Line (11,-1.2)-(13,-1.2)
 GLocate (14,-1.1)
 GPrint "感情"
 Call DrawBioCurve(BY,BM,BD,TY,TM,28)

'--------------------------------------
 ForeColor = "Green"
 Line (21,-1.2)-(23,-1.2)
 GLocate (24,-1.1)
 GPrint "知性"
 Call DrawBioCurve(BY,BM,BD,TY,TM,33)
End

'--------------------------------------
'--------------------------------------

Sub DrawBioCurve(BY,BM,BD,TY,TM,m)
 For i=0 to Month(TM)-1
   x1 = i 
   y1 = Sin((DaysFromBirth(BY,BM,BD,TY,TM,x1)/m)*2*Pi) 
   x2 = i+1
   y2 = Sin((DaysFromBirth(BY,BM,BD,TY,TM,x2)/m)*2*Pi)
   Line (x1,y1)-(x2,y2)
 Next i
End Sub

Function DaysFromBirth(BY,BM,BD,Ye,Mo,Da)
   If Ye > BY then
      Days = 365 - DaysFromNYDay(BY,BM,BD) + 1
      If IsLeapYear(BY) then Days = Days + 1
      For i=BY+1 to Ye-1
         If IsLeapYear(i) then
            Days = Days + 366
         Else
            Days = Days + 365
         End if
      Next i
      DaysFromBirth = Days + DaysFromNYDay(Ye,Mo,Da)
   Else 
      DaysFromBirth = DaysFromNYDay(Ye,Mo,Da) - DaysFromNYDay(Y,M,D) + 1
   End if
End Function


Function DaysFromNYDay(Y,M,D)
   If IsLeapYear(y) then Month(2)=29
   Ds = 0
   For i=1 to M-1
      Ds = Ds + Month(i)
   Next i
   DaysFromNYDay = Ds + D
End Function

Function ThisYear
   D$=Date$
   YY$= Split$(D$,"/")
   if Len(YY$)=2 then YY$= "20"+YY$
   ThisYear = Val(YY$)
End Function

Function ThisMonth
   D$=Date$
   YY$= Split$(D$,"/")
   MM$= Split$(D$,"/")
   ThisMonth = Val(MM$)
End Function

Function Today
   D$=Date$
   YY$= Split$(D$,"/")
   MM$= Split$(D$,"/")
   DD$= Split$(D$,"/")
   Today = Val(DD$)
End Function

少し長いプログラムですが,モジュール化して書いてありますから,個々の部分をチェックするだけで良いわけです。 そのようにしてみると,それほど難しいプログラムではありません。


 誕生日からの日数の計算のプログラムはここ,バイオリズムの計算のプログラムはここにあります。