2009年3月27日金曜日

米欧回覧実記

久米邦武の「米欧回覧実記」では, 日付が2つ書いてあるのに気づく. 例えば最初に「明治4年11月10日 冬至 西暦1871年12月12日」とある. 日本で太陽暦にしたのは, 明治5年12月だから, この時はまだ太陽太陰暦で, 明治4年はその日付. 西暦は太陽暦である. 我々が, 今日は旧暦の正月だと, 旧暦を意識するように, 昔の人は, 新暦では何日と知っていたのであろうか.

「11月21日ハ西洋暦ニテ1872年1月1日デアル.」 という記述もある.

青木信仰「時と暦」で, 「ケプラーのような人の手紙では, Leipzig. 11./21.Okt. 1630というようになっており」を読んだ時には, 天文学者ならそうかと思った程度であったが, 明治はじめの日本でもこうであったかと認識した. もっとも「米欧回覧実記」は帰国して書いたから, 出発の時は, 知らなかったかもしれない.

そもそも序文に「明治4年11月10日ニ起リ, 6年9月13日ニ止ル(即西暦1871年12月12日ヨリ同73年9月13日マデ)スヘテ全1年9ヶ月21ヶ日ノ星霜ニテ」と書く. 旅の終りの日が合っているのは, その間に改暦したからだ.

Keplerの記述でなるほどと思うのは, カトリックの国では, すでに1582年に改暦し, 10日飛ばしたので, Keplerの日付の差もちょうど10日なことだ.

それに対して, 米欧回覧実記の日付は, 多少怪しい. そもそも新暦で, 12月12日が冬至だろうか. そしてその10日後が新年であろうか. どうも11月10日が12月12日というのがおかしい.

インターネットで調べると, 驚いたことに新暦から旧暦を教えてくれるページがあった.
http://koyomi.vis.ne.jp/i/9rekical.php
ここで1871年12月を見ると, 新暦12月21日が旧暦11月10日になり, 新暦12月31日が旧暦11月20日になる. だから新年の記述は正しかった. ついでに1872年12月を見ると, 新暦の12月31日は旧暦12月2日であり, 12月2日の翌日を明治6年1月1日にしたのであった.

米欧回覧実記に「西洋ニテハ国都ニハ必ス司天台アリテ経度ハ是ヨリ数ヘ起ス」とあるのも気になる. 確かに伊能図の経度の中心は京都の三条大橋あたりにあったと思う. 前掲「時と暦」によると, 国際子午線会議があったのは, 1880年だから, 米欧回覧実記の頃は, まだバラバラだったわけだ.

ところで, 緯度経度はいつ頃から使われていたのだろうか. 米欧回覧実記でも, 例えば「波士敦(ボストン)府ハ「マッサッセッチュ」州の首府ニテ, 北緯42度20分, 西経71度54分に位シ」のような記述が多い.

曲亭馬琴の「椿説弓張月」には, 琉球の説明に, 「抑彼國は, 北極地を出ること26度2分3厘」とあるから, 1805年頃の馬琴にはそういう知識があった.

「時と暦」には「プトレマイオスの時代でも, 1度よりよい精度はあった」とあるから, 地球が丸いと分かった頃から, 天文学者などには, 緯度経度は認識されていたであろう. 興味があるのは一般人はいつ頃知ったかである.

2009年3月23日月曜日

個人用電卓のプログラミング

情報科学標準問題の1つにfactorialがある.

(define (factorial n)
(if (= n 0) 1
(* n (factorial (- n 1)))))

個人用電卓のプログラムでも, この程度のことはやってみたい. プログラム名としては「!」を使うことにしよう.

nがスタックトップにあるとき, これを複製し, 1を引き, !でfactorialをとり, *で掛ければよい. 問題はnが0の時には1を返す仕掛けを組み込むことである. 0と1以上の判定は, 符号を反転して負になれば元は≥1であったわけだ.

従ってプログラムはこうなる.

("_6_G1+5_"G"1-!*)!=
0123456
012345

このプログラムの開始時, nを複製し, 符号反転する. その上に-6を置き, ジャンプの準備をする. G命令で6文字右へ飛ぶ. プログラムの下のGの隣りから012...とあるのが飛び先で, 次のGの右の"まで行く. そこで複製し, 1を引き!でfactorialを再帰呼出しする. n-1のfactorialがとれて戻ってきたら, *で掛ける. 一方0だったら, Gではジャンプせず, n(つまり0)に1を足し, 返す値1を作る. 次に-5を2個積んでG命令でプログラムの終りまで飛ぶ. -5を2個置くのは, 上は飛び先, 下は負ジャンプを絶対ジャンプにするためである.

factorial 3の実行の様子は下の図の通り.



一番左はGからの相対位置. 次は命令. (3)から始まる列は最初の実行トレース. G命令で下へ飛ぶ. そのうち, !命令になると, 次に右の列の"からfactorialを再帰実行する.

3回目の再帰実行は, スタックが0の時で, 処理の流れが異る. つまりG命令でジャンプせず, 1を置いて(正しくは0に1を足して)飛び出す.

戻ると1つ左の最下行*に来, 1と1を掛け1にして飛び出す. また左の最下行*で1と2を掛け, 次の左で2と3を掛け, 結果は6になった.

2009年3月18日水曜日

個人用電卓のプログラミング

昨年10月頃, このブログに書いた個人用電卓は, 機能を拡張したヴァージョンが, シミュレータ上で快適に稼働している.

今回はそのプログラミング技法を紹介する.

Schemeで書いたシミュレータは, スタックの代りにリストを使う. car側がスタックトップである. 電卓実機はスタックを突き破ってポップも出来るが, リストではそうはいかぬ. また実機は2の補数の64ビットであったが, シミュレータはbignumである.

シミュレータには押しボタンはないから, それに相当する文字を決める.
0〜9は文字も09.
十六進のA,B,...,Fは小文字でa,b,...,f.
算術演算+,-,*,/はそのまま.
基数変換Hex, Dec, OctはH,D,O.
数値を区切るEntはE.
Pop, Dup, Exc, Chsはそれぞれ ^,",:,_.
Sqt, Fct, Pow, JDはそれぞれS,F,P,Jである.

従って3*(2+1)は, 3E2E1+* と入力する. リターンは無視.

拡張機能には, まず補助スタックが出来た. これも実態はリストである.
命令は2個

U スタックをポップし, そこにあったものを補助スタックにプッシュする.
N 補助スタックをポップし, そこにあったものをスタックにプッシュする.

こうすることで, 例えばスタックトップの4個を回転する:
:U:U:NN(d c b a ...)(c b a d ...)とすることが出来る. まず:でスタックは(c d b a ...)になる; Ucは補助スタックへ移り, (... c) (d b a ...)になる. 左側にあるリストが補助スタックで, スタックトップが右に書いてある. 2番目の:でスタックは(b d a ...)になり, U(... c b) (d a ...)になり, 3番目の:(a d ...)になり, NN(... ) (c b a d ...)になるのである.

こんなことをやっている内に, このプログラム列を記憶し, 繰り返し使いたくなった. そこで (:U:U:NN)R= と入力して, プログラム列をRという名前で記憶する. R(d c b a ...)(c b a d ...)になるので, RRRとすると(d c b a ...)がこの4段の回転を3回実行し, (a d c b ...)になるのである.

さらに欲が出てきて, プログラムの中で条件ジャンプがしたくなった.

G スタックのトップから2段目が負なら, スタックトップの数だけプログラムを戻る.

10から1までの和を計算するプログラムは次のようだ.

(0Ua"N+U1-"_aG^N)X=

と定義し, Xで起動する. 実行の様子は下の通り.



上の図では, 左の方に命令が縦に並べてある. 一番左の下から0,1,...とあるのは, G命令でジャンプする相対番地である. 10回目でループを抜けると, 主のスタックトップに和の55が出来ている.

ここまで来れば鬼に鉄棒である. もっと難しいプログラムの例はまた次回に.

2009年2月23日月曜日

多面体描画道楽

PostScriptのすごいのは, 座標の拡大縮小, 移動, 回転などをやってくれることである. 別のいい方ではaffine変換をしてくれる. 例えば下の図で, 左上は縦横等間隔に平行線を引いたものである. 右上はひしゃげた形になっているが, 等間隔の平行線に違いはない.

PostScript的な表記では, 左の図のp(x,y)は右ではp'(x',y')に移動していて,
x'=ax+cy+tx
y'=bx+dy+ty
となっていて, 今の場合, パラメータはそれぞれ
a=1.2, b=0.5, c=0.3, d=0.8, tx=ty=0
である. (tx=0だから, 2つの図は重なる筈だが, 見えにくいのでずらしてある.)

左下の正五角形を同じように変換したのが, 右下のである. こういう変換は文字フォントについても出来て, 少し前までの国土地理院の地形図は, 山の名は右肩あがりの文字, 川や湖, 海の名は上端を左にずらした文字(イタリックと逆)で表示してあった. 次の箱根山と芦ノ湖がその例だ.

さて, 改めて考えてみると, 正十二面体の各面の投影された五角形は, 真正面から見た(つまり通常の)正五角形を適当にaffine変換したものであった. だから各面の変換パラメータ, a, b, c, d, tx, tyが決れば, その環境で単に正五角形を書けばよい筈である.

x方向についてa, c, tx, y方向についてb, d, tyを決めたいから, 直線上にはない3つの点があればよい. 前回のA面について考えれば, 頂点0, 2, 4の真正面から見たx, y座標(3次元でいえばy, z座標)
0=(-l0, 0), 2=(0,l2), 4=(l0,0)
であったから, これがそれぞれ(x0,y0), (x2,y2), (x4,y4)に移動したとすると,
x0=a.(-l0)+c.0+tx, x2=a.0+c.l2+tx, x4=a.l0+c.0+tx
y0=b.(-l0)+d.0+ty, y2=b.0+d.l2+ty, yr=a.l0+d.0+ty
従って
tx=(x0+x4)/2, a=(x4-tx)/l0, c=(x2-tx)/l2,
ty=(y0+y4)/2, b=(y4-ty)/l0, d=(y2-ty)/l2
と得られる.
各面についてこれらのパラメータを計算すると, PostScript風には
gsave
[a b c d tx ty] concat
l0 neg 0 moveto l1 neg l1 lineto 0 l2 lineto l1 l1 lineto l0 0 lineto closepath
stroke
grestore
で描けてしまう. 分かってみるとなーんだということになる.

前回の最初の図の各面にあるA, B, C,...など面の名は, 実はこうして描いたものであった. (だから見えない面の名は裏返しになっていた.)

これまでは5つの頂点すべてを変換していたが, この方式では3つだけでよい. しかし, 正多面体では正三角形の面のものが多いから, これでは得にはならず, 正多面体描画道楽で利点があるのは正十二面体(と正六面体)だけであるが, こういうことを考えておけばまた役立つこともあろう.

2009年2月20日金曜日

多面体描画道楽

正多面体の図を何度も書いているうちに, 結構上達してきた. 今回は正十二面体を例に, 私流の描き方を説明したい.


ここに示すのが正十二面体である. 赤がx軸, 緑がy軸, 青がz軸である. 基本の面として正五角形の頂点に0,1,...,4と番号のある面(A)をとる.

以前のブログ(2008年9月19日)にあった正五角形は, 2と3でこの基本面に接している右上の面(E)である.

とりあえず正五角形の対角線の長さを思い出してみる.

1辺ABの長さを1とする. 対角線ACを計算したい. ニ等辺三角形だから∠BAC=∠ACB=∠CBD=αである. ∠BDAは三角形の外角だから2αである. これは内側の小さい正五角形の外角でもあるから, 72度であり, 従ってαは36度である. ∠ABCは正五角形の内角だから108度で, ∠CBD=36度だから, ∠DBAは72度 =∠BDA ∴△ABDは2等辺三角形であった. 従ってAD=1. △ABCは△CDBと相似だから CDの長さをaとすると, (a+1)/1=1/a 従ってa=(√5-1)/2, 対角線の長さはa+1=(√5+1)/2≒1.6180つまり黄金比である.

これがわかれば正十二面体のAの面の各頂点のx,y,z座標が決る.
頂点0と頂点4の間の辺の長さを2とすると,
頂点0の座標:(?,-1,0) (x座標は後で決める)
頂点4の座標:(?,1,0)
頂点2の座標:(1,0,?)となる.
次に頂点3のx座標はE面の対角線なので, (√5+1)/2. y座標はA面の対角線なので, (√5+1)/2. z座標はI面の対角線なので, (√5+1)/2.
つまり
頂点1の座標:((√5+1)/2,-(√5+1)/2,(√5+1)/2)
頂点3の座標:((√5+1)/2,(√5+1)/2,(√5+1)/2)
となる.
ところで正多面体は球に内接するから, 中心から頂点3までの長さと頂点4までの長さは等しい. 従って頂点4のx座標をxとすると
x2+12+02=3*(√5+1)/2)2
従ってx2=(6√5+18)/4-1=(6√5+14)/4. x=(√5+3)/2.

座標に使う長さを l0=(√5+3)/2, l1=(√5+1)/2, l2=1とすると,
A面の頂点の座標は, 頂点を面の外側から見て時計回りに
(list (list l0 (- l2) 0) (list l1 (- l1) l1) (list l2 0 l0) (list l1 l1 l1) (list l0 l2 0))
である. 回り方を決めるのは, 隠面消去のために各面の法線を計算するから .

残りの11の面は, 対称性を考えればx, y, z軸まわりの直角の回転, yz, zx, xy面に対する反転で得られる. すなわち
B面はA面のxy面に対する反転 C面はA面のyz面に対する反転
D面はC面のxy面に対する反転 E面はA面をx軸まわりの回転のy軸まわりの回転
F面はE面のzx面に対する反転 G面はE面のxy面に対する反転
H面はG面のzx面に対する反転 I面はE面のy軸まわりの回転のz軸まわりの回転
J面はI面のyz面に対する反転 K面はI面のzx面に対する反転
L面はK面のyz面に対する反転
である. 反転の場合は頂点の時計回り順を維持すべく, リストを逆順にする.

これですべての面の頂点の座標が揃った.
上の図は正面から見た図を, z軸まわりに15度回転し, さらにy軸まわりに-15度回転してから, 正面(x軸方向)から見た図である. 前のブログの記述の「左に寄せる角度をθ, 手前に引く角度をφとする」との対比では, θはz軸まわりの回転角, -φがy軸まわりの回転角である.

すべての座標を上述のように回転し, x軸方向から見た絵を描くには, y座標を2次元画面のx座標に, z座標を2次元画面のy座標にするだけでよい.

隠面消去も簡単である. すべての面の法線方向を求める.
それには頂点リストの0番-1番, 2番-1番で, 1番から出た0番方向と, 2番方向のベクトルが得られ, この外積をとると各面の法線方向が得られる. そのx成分が正ならこちら向きの面だし, 負ならあちら向きの面である.
すべての面をこうしてx成分の負のものと, 正のものに分け, あちら向きの面を灰色の線で描画した後, こちら向きの面を黒で描画した.

いい忘れたが, 今回の計算はすべてSchemeで行い, 最後にPostscriptのファイルを出力した. 座標軸や面の文字は, こうして出来たPostscriptのファイルに追加したものである.

2009年2月13日金曜日

ヴァレンタインデイ

節分がすんだと思ったらもうヴァレンタインデイだ. 皆さんはチョコレートを連想するだろうが, 私の場合はShakespeareの戯曲のHamletにあるOpheliaの歌である.

4幕5場ですでに正気を失っているOpheliaが歌う. 「明日はヴァレンタイン」と. とりあえずは明日がヴァレンタインデイから連想したのだが, もう少し続ける.

To-morrow is Saint Valentine's day,
All in the morning betime,
And I a maid at your window,
To be your Valentine.
Then up he rose, and donn'd his clothes,
And dupp'd the chamber-door;
Let in the maid, that out a maid
Never departed more.

小田島訳はこうだ.

ヴァレンタインのお祭の日は
  朝早くからいそいそと,
恋しい人の窓辺に立って
  乙女の胸をときめかす.
恋しい人は部屋の戸開けて
  迎え入れるの手をとって
入った娘が出てくるときは
  もはや娘じゃないからだ.

逍遥訳はこうだ.

あすは十四日ワ"レンタインさまよ,
門(かど)へ行こぞや, 引明方に,
ぬしのお方はなろずもの.
それと見るより門の戸あけて,
ついと手を取り引入れられたりゃ
純潔(うぶ)な處女(むすめ)ぢゃ戻られぬ.

この2人の訳にはいつも時代の変遷を感じる.

このあたりのOpheliaのセリフはひたすら悲しい. そして5幕7場の王妃のセリフも嘆きに溢れている. 有名なMillaisのOpheliaの絵はこのセリフに基づいている.

ところでOpheliaの「valentine」をどうやって探すかだ. 私はアメリカ滞在中に求めた, 1600ページもの「The Harvard Concordance to Shakespeare」を持っているので, 検索はいつでも出来る. Concordanceはコンピュータ屋の言葉ではKWICインデックスである. これで「valentine」を引くと, Hamletには上記の2語しか見つからない. 驚くことに「valentine」が50回以上現れる戯曲があった. Two Gentlemen of Veronaである. この2人の紳士のうちの1人がValentine君であった.

ブラウザがあれば, 検索は簡単だ. http://shakespeare.mit.edu/へ行くとcommediy(喜劇), history(史劇), tragedy(悲劇)の目次があり, 例えばそこで悲劇のHamletへ行く. 左上にEntire play in one pageというリンクがあり, それで全体を取り込み, 検索するのである.

このURLを忘れたら, complete works of shakespeareでgoogleサーチすればよい.

2009年2月3日火曜日

節分

春節(旧正月)がすんで1週間たったので, 夜外へ出てみたら, 上弦の月が霞んでいた.
「月も朧に白魚の篝も霞む春の空」
になったのかも知れない.
「ほんに今宵は節分か」
は白波五人男のせりふ.

NHKのテレビは変なことをいっていた. 今日は節分, だから明日は立春と.
逆ですよね.

夜, 豆まきをした. いつも私の役目だ.

私の子供のころ, 母親がやっていたことを未だに私はやっている.
家族それぞれの年齢の数だけの大豆を集めて半紙に包む.
昔はそれに1銭硬貨もいれてお捻りにする. (今は1円)

年の数が多いと, 10の桁の数と1の桁の数を足したものにする. それでも多いときは? もう一度このようにする. たとえば78歳なら78粒は多いので7+8=15とする. それでも多ければ1+5=6とする. 繰り返すのはいやなので閉じた式にする. つまり(modulo n 9)となる.
9歳の子供は9粒だから, (+ (modulo (+ n 8) 9) 1)というべきである. でも今度は0歳が9粒になってしまった. はて? それはさておき...

それで家族一人一人の背をさすり, 外へ出て四つ角へ棄ててくる.
後は後を振返らずに家に帰る.

それで外へ出, 月を見たのであった.

そういう伝統はいつまで続くかなぁ.