2008年10月31日金曜日

ユリウス日

数日前に書いた個人用電卓にユリウス日のキーがあった. これは特に週日を求めるためのものである. ユリウス日に1を足し, 7で法をとると日曜を0, 月曜を1, ..., 土曜を6とする週日が得られるのである. またこの電卓は, 除算のとき, スタックトップには商が, そのすぐ下には剰余が出るので, 20081020 [JD] 1 [+] 7[/] [Pop] -> 1 となり, 本年10月20日は月曜と分かる. -4712年1月1日も月曜であったわけだ. ユリウス日は, -4712年1月1日 世界時正午を0.0とし, それからの通日である. 2008年10月20日のユリウス日が2454760というのは, 正確にはその日の世界時正午, JSTで午後9時のユリウス日が2454760.0であるということだ. それを省略してその日のユリウス日という. -4712年1月2日のユリウス日は1である. 理科年表や天文年鑑にも計算用の表がある.
A表              B表    *   C表      *
-1000 1355808     0  0,-1    1   0   0
 -900 1392333     1   365    2  31  31
 -800 1428858     2   730    3  59  60
 ...              3  1095    4  90  91
 1300 2195883     4  1460   ...
 1400 2232408     5  1826   11 304 305
 1500 2268933    ...        12 334 335
 1500 2268923    98 35794
 1600 2305448    99 36159
...
 2000 2451545
例えば2004年4月23日のユリウス日ならA表から2000年の2451545, B表から4年の1460, C表から4月の右の閏年用の91をとり, それに23を足して(+ 2451545 1460 91 23) -> 2453119が得られる. このA表は, 例えば2000年なら, -4712年1月1日から1999年12月31日までの日数である. 従ってこれは2001年1月1日のユリウス日のになりそうだが, B表の最初0年に, 閏年なら-1, 平年なら0とあるのが重要で, 2000年は閏年なので, 1引くから結局1月0日のユリウス日になる. 変換の式もサーチエンジンで探せるが, 私が情報処理学会誌のHaskell Programmingに書いた,
mon0, mon1 :: [Int]
mon0 = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]
mon1 = [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335]

gleap, jleap :: Int -> Bool -- Gregorian, Julian暦のうるう年
gleap y = if y `mod` 100 == 0 then y `mod` 400 == 0
                              else y `mod` 4 == 0
jleap y = y `mod` 4 == 0

julianDate :: Int -> Int -> Int -> Int
julianDate y m d =                   -- aからgは途中の値
 let a = (y + 4712) * 365
     b = (y + 4712 + 3) `div` 4
     c = if y > 1601 then y' `div` 400 - y' `div` 100 else 0
           where y' = y - 1601
     e = if [y,m,d] >= [1582,10,15] then -10 else 0
     f = (if leap y then mon1 else mon0) !! (m - 1)
           where leap = if y > 1600 then gleap else jleap
     g = d - 1
  in a + b + c + e + f + g           -- 最後の結果
のようにも書ける. インターネットなら, https://www.onlineconversion.com/julian_date.htmにJulian Date Converterがあり, Year, Month, Day(, Hour, Minute, Second)を入れ, Computer Julian dateを押すと結果が返ってくる. 個人用電卓では結局上の式を使った. 電卓は実はやっとiPod touchに実装した. 電車の中でもテストが出来て楽しいが, 実用化にはまだ改良の余地は多々ある.

2008年10月29日水曜日

多面体描画道楽

TAOCPにこういう絵がある. (演習問題7.2.1.2-60)

{0,1,2,3}の24通りの全順列を, 隣り同士の交換で実現しようというものである. 天辺にある0123を最初の順列とする. 左の2個を交換すると1023になり, それは天辺から左へ稜線を辿ると出会う1023である. 次は右の2個を交換し1032が得られる. このようにオレンジ色の線を一筆書きでたどれば全順列を通過するというわけである. これはこの立体のHamilton閉路(つまり全頂点を回って元へ戻る経路)になっている.

この立体は英語では"truncatedoctahedron", 日本語では「切頭八面体」というらしいが, いまいちな感じだ. これは正八面体の頂点を切り落としたものである.

赤い線で示すのが正八面体で, 黒線のように切り取る.

ところでこの立体は, 正八面体の頂点を削れば出来るが, 立方体(正六面体)をの頂点を削っても出来る.


従って「切頭六面体」でもある. ただ削り取る量ははるかに多い. もともとこの立体には, 正方形が6枚, 六角形が8枚あるのだが, 正八面体の6つの頂点が6枚の正方形に辿り着き, 立方体の8つの頂点が8枚の六角形に辿り着く.

同様なものには, サッカーボールともいわれる, 「切頭二十面体」がある. (truncatedicosahedron)



これも, 名前が示すように, 正二十面体の12個の頂点から削り, 12個の正五角形に辿り着くのと, 正十二面体の20の頂点から削り, 20個の正六角形に辿り着くのがある.



赤線で示す正二十面体の頂点から削って, 「切頭二十面体」を作る.



この方は赤線で示すのが正十二面体であり, その頂点から削り始めると, 正五角形の面が段々と削られ, 小さい正五角形が現れる.

さらに削り続けるとどうなるか. 正五角形は消滅して頂点になる. 一方正六角形は正三角形になる. 要するに正二十面体になってしまう. これが正十二面体と正二十面体は相対の関係にあることの証明である. 一方から他方へ移るちょうど途中にサッカーボールがあったのだ.

このことは, 最初の立体でも同じで, 正六面体と正八面体は相対の関係にあることが分かる. 正四面体は自分同士で相対の関係にある.

ではその途中はどういう立体か. その「切頭四面体」
(truncatedtetrahedron)を書いてみた.



あまり見かけない立体ではあるが, 4個の頂点から現れた正三角形が4個の正三角形を六角形にして浸食し, ついには頂点になり, 正三角形の方が面になって, 面と頂点の機能を逆転した正四面体になる. この六角形がちょうど正六角形になった瞬間が上の図である. つまり削られて短くなりつつある元の稜と, 削りながら長くなりつつある新しい稜の長さはどこかで等しくなるのである. この点の座標の計算は簡単である. 逆転した正四面体を青線で示す.

2008年10月28日火曜日

個人用電卓

Hewlett Packardの電卓16Cを愛用していた. 自分でもそういう電卓を設計したいと思い, 何年か前にHappy Hacking Calculatorのシミュレータを書いた. これはパソコンの中で動いているので, 計算するならパソコンを使えばよく, お遊びの域を出なかった.

それが最近, iPod touch用のシミュレータがあるので, iPod用に書き直してみた. それについて書いてみたい. (HHCalcの手引き)

見かけは下の通りである.



左半分が入力キー, 右半分が演算キーである. 入力キーの上部に結果を表示する.

演算の機能は次の通り:

[/] y/x
[*] y*x
[-] y-x
[+] y+x
[Hex] 基数を16進に
[Dec] 基数を10進に
[Oct] 基数を8進に
[Ent] 入力終り
[Pop] スタックトップを捨てる
[Dup] スタックトップを複製
[Exc] x<->y
[Chs] -x
[Sqt] √x
[Fct] xの素因数分解
[Pow] xのy乗
[JD] ユリウス日 2008年10月20日のJDは 20081020 [JD] ->2454760
-4712年1月1日のJDは 47120000[Chs]101[+][JD] -> 0

今のところはシミュレータで動いているだけだ. [JD]のようなマイナーな機能は別画面で指定するようにし, [JD]の場所は別画面起動用にするのもいいかと考えている.

2008年10月2日木曜日

単調関数

The Art of Computer Programming の先の方を読んでいたら, monotone-function function というのに出会った. もちろん, monotoneな関数とは, 単調な, 俗語でいえば「右肩上がり」か「右肩下がり」なものである.

しかし単調関数の関数となると, どうもそう簡単なものではないらしい. そこでの説明は以下の通り. 式が多いので, texで書いて張り付けてある.



上のμnの式の右辺のbigwedgeの下にある, 0≤ij≤2nは, 「nビットのiの各ビットがjの各ビットより大きくない対について」という意味である.

TAOCP流にいうと, the bit string i=i0...in-1 is regarded as contained in or equal to the bitstring j=j0...jn-1 if and only if ikjkfor all k.


これでやってみるとmonotone functionは
0変数で2種類(0, 1),
1変数で3種類(0, x, 1),
2変数で6種類(0, xy, x, y, x&ory, 1)あり,
3変数の20種類は以下のとおりである.
0, (∧ x (∧ y z)), (∧ y z), (∧ z x), (∧ (∨ x y) z), z, (∧ x y), (∧ (∨ z x) y), y, (∧ (∨ y z) x), (∨ (∧ x y) (∨ (∧ y z) (∧ z x))), (∨ (∧ x y) z), (∨ (∧ z x) y), (∨ y z), x, (∨ (∧ y z) x), (∨ z x), (∨ x y), (∨ x (∨ y z)), 1

3変数関数はSchemeでチェックしたので, Cambridge Notationになっている.
monotone functionは否定なしで, ∧, ∨ だけで書けるというのはこれで分かる.



この図では, 各キューブが1つのmonotonic functionを示す. 座標軸はxが手前, yが右, zが上である. 角の黒丸が関数値が1になることを示す. 左上が3変数関数の0に, その右隣りがxyzに, のように対応している. 右下が最後の1である. 大学にいた頃, monotonic functionは, このキューブを羊羮だと考え, 黒丸のコーナーと黒丸なしのコーナーが包丁で一度に切り分けられるもの, といったことがある.その様子は見て取れよう.

ついでだが, この図で黒丸の数は0から8まである. 0個の関数は1, 8個のは1である.
1個のは xyz, 7個のは xyzである.
2個のは xy 型, 6個のは xy 型だ.
3個のは x ∧ (yz)型, 5個のは x ∨ (yz)型.
4個のは x 型か (xy) ∨ (yz) ∨ (zx)=(xy) ∧ (yz) ∧ (zx) これは自己相対で<x, y, z> (多数決)である.

μnの真理値表は以下の通り:

μ0=(1,1)
μ1=(1,0,1,1)
μ2=(1,0,0,0,0,0,0,0,1,0,1,0,1,0,1,1)

最後の真理値表から, 2変数関数が単調になる真理値は(一番左を0番として)
0,0,0,0(0番)
1,0,0,0(8番)
1,0,1,0(10番)
1,1,0,0(12番)
1,1,1,0(14番)
1,1,1,1(15番)
だから, 0,0,0,0は0に, 1,0,0,0はxyに, 1,0,1,0はyに, 1,1,0,0はxに, 1,1,1,0はxyに, 1,1,1,1は1に対応する.

この出てきた文脈は, BDD(binary decision diagram)の合成である. これについてはまたにしよう.

2008年9月26日金曜日

パラメトロン計算機完成50年

本年(2008年)3月26日のパラメトロン計算機PC-1の完成50年記念から半年がたつ.

記念の日の講演会会場で, NIIの橋爪君たちのパラメトロン加算回路のデモがあったが, それ以外にもこの半年にはパラメトロンのニュースがいくつかあったので記録しておく.


NTTの研究所でもパラメトロンの試作をしているというニュースを読んだ.

「パラメトロン・コンピュータよ再び」NTT研が低消費の論理素子を開発 EE Times Japan 2008年6月号

長さ250μm, 幅85μm, 厚さ1.4μmの長さの両側から圧電で正弦波の力を加えると, 上下に曲がりながら振動する. それが0相, π相になるという.


9月になると, 逗子の井村さんから, パラメータ発振に成功したというメイルを貰った. 励振と発振の様子NOTらしいものが見える.

ただ加算回路までは出来ていないらしい.

パラメータ励振に興味を持つ人がいるのは嬉しいことだ.

2008年9月19日金曜日

多面体描画道楽

小学生の頃, 算術か図画か工作の教科書に正五角形の書き方が載っていた. 正三角形, 正方形, 正六角形ならコンパスで描けるが, 正五角形は分度器を使うものと思っていたから, この方法には驚かされた. その後, 1辺の長さ1の正五角形の対角線の長さが(√5+1)/2であることを知ると,なんのことはなく, 驚きは霧散した.

この描き方は正五角形の書き方をサーチエンジンで探せばあるだろうが, 図のように底辺ABを引く. 辺の長さを1とする. その中点Cから垂線を立て, CD=1の点Dをとり, ADをDの方向へ延長してDE=1/2に点Eをとる. AEに等しくCDの延長線上にAFをとると, Fは正五角形の頂点になる.



正五角形をPostScriptで描くのは簡単だ.
/l 200 def     % 辺の長さ
0 0 moveto % 左下の位置へ移動
0 72 216 {dup cos l mul exch sin l mul rlineto} for
% 0度から72度おきに216度まで
closepath stroke


描いて楽しいのは正多面体である. 高木貞治先生の「数学小景」には, 正十二面体と, 正二十面体のEuclid幾何学原本による描き方が載っている.

どちらも立方体から始める. 正十二面体では, 面を構成する正五角形の対角線を1辺とする立方体をまず描く. これが内接立方体になる. 対角線を1とすると, 辺の長さは(√5-1)/2である. これををaとする. 立方体の上のの面には, 中央に前後に長さaの線を引く. 左右の面には, 中央に上下に, 前後の面には左右にそれぞれ長さaの線を引く. 図ではこれらの線を多少太めに示した.

さて上の面の線の両端U,Vから上方へ長さa/2の線UP, VQを立てる. 右の面の線の上端から右へ長さa/2の線WRを立てる. こらP,Q,Rと元の立方体の頂点A,Bとが正五角形になる.

中央の線は各面にあるから計6本で, そのそれぞれから2枚の屋根のような正五角形が作られるから, 十二面体になる.




一方正二十面体は同じような立方体の内部に作る. これが今度は外接立方体になる. 先ほどの各面の中央の線の両端U,V,W,X,Y,Zの隣り同士を結べばよい. すると三角形の屋根が12枚の他, 立方体の頂点に対応する三角形が8枚あり, 合わせて二十面体になる.

ここからはご用とお急ぎのないお立ち会いに. 私のかような図の描き方をご披露する.

上の図で, 私は手前をx, 右手をy, 上をzと見ることにしている. そして手前を左に寄せ, 上を手前に引き, x軸方向から見た位置に各点を移して描く. 左に寄せる角度をθ, 手前に引く角度をφとすると, 画面の左右方向Xと上下方向Yについては

X=- x sin θ + y cos θ+ 300
Y=(-x cos θ - y sin θ) sin φ+ z cos φ + 400
(300と400は原点を適当に移動)

だから, x, y, zを変換(map)し, X, Yに移動し(moveto), または線を延す(lineto)命令をmm, mlとすると

/phi 15 def /theta 15 def
/map {3 dict begin /z exch def /y exch def /x exch def
x theta sin mul neg y theta cos mul add 300 add
x theta cos mul neg y theta sin mul sub phi sin mul
z phi cos mul add 400 add end} def
/mm {map moveto} def /ml {map lineto} def


基盤の立方体は直ぐ描けて(稜の長さの半分lは多面体ごとに決める)
/ln l neg def
l l ln mm l l l ml l ln l ml l ln ln ml l l ln ml ln l ln ml
ln l l ml ln ln l ml l ln l ml l l l mm ln l l ml stroke

でよい.

正十二面体では
/l 1 5 sqrt add 2 div 60 mul def
/a 5 sqrt 1 sub 2 div l mul def /an a neg def

とした後
a 0 l a add mm %P
l l l ml %A
0 a l add a ml %R
ln l l ml %B
an 0 a l add ml %Q
a 0 l a add ml stroke %P

正二十面体では
/l 1 5 sqrt add 2 div 80 mul def
/a 5 sqrt 1 sub 2 div l mul def /an a neg def

とした後
an 0 l mm %V
a 0 l ml %U
l an 0 ml %Y
l a 0 ml %Z
a 0 l ml %U
0 l a ml %W
l a 0 ml %Z
0 l a mm 0 l an ml stroke %W X

で描くことが出来る.

数学小景には『正十二面体と正二十面体とは, 自然界が産み能わざる結晶で, それは純然たる「脳産物」である. 』の記述がある.

2008年9月14日日曜日

八進法算盤

下の図は, 私が1960年代の始め頃使っていた, 八進法の算盤である.



当時の計算機はIBM7040で, これはIBM704と同様のアーキテクチャゆえ, 命令語もデータも, 1語36ビットであった. 命令語はその36ビットを左からprefix(3ビット), decrement(15ビット), tag(3ビット), address(15ビット)の部分に分けた. このaddressとdecrementがLispでいうcarとcdrの語源になっているのは周知のとおり. (car=content of address part of register, cdr=content of decrement part of register) 各部分が3の倍数のビット数なので, 命令語の表示は八進法だったのである.

従って, コンソールの前で, 八進法の計算(加減算だけだが)をすること, しばしばであった.

その時考えたのは, 市販の算盤は十進法だが, 下の1の珠を1個外せば, 八進法の算盤として使えるということだ. 早速12桁の算盤を売っていないかと探したが, 市販の算盤はすべて奇数桁であり, 12桁のものはなかった. やむを得ず13桁の算盤を買い求め, 糸鋸などで縮めたのが, 上掲の算盤である.

通常は上が5の珠, 下が1の珠だが, 八進法算盤では, 上が4の珠となる. それ以外は十進法での計算と余り違わない.

この算盤は多いに実用的であった.

引き出しにまだ残っていたので, 実物の写真も載せておく.


八進法算盤

私が小学校で習ったときは, 下の1の珠は4個であったが, 私の母は1の珠が5個の算盤を使っていた. そのずーっと前は, (中国だけかも知れないが) 上の5の珠も2個あったらしい. 1の珠5個で十進法の計算をしていたことを考えると, なにも下の珠を外さなくても, 八進法で計算出来たわけだが, 実際にやってみると改造算盤には及ばない.

余談だが, 昔は病院にいくと, 4号室とか19号室とかはなかった. 4と9は「死」と「苦」を連想するので, 使わなかったのだ. 0,1,2,3,5,6,7,8の8個の数字を使うから, これも一種の八進法である. 私の算盤で, 上の珠を5と解釈すると, この八進法になる. 私はこの八進法を通常のと区別するため, 迷信法といったことがあるが, 東京女子大学の水谷先生がこの命名に興味を持たれたらしい.

最近のアーキテクチャは, 十六進法が多いので, 八進法算盤はお蔵入りになっている. 十六進法算盤はどういう構造にすべきか, 上下それぞれ3個というのもありかも知れないが, 操作出来るだろうか. 目もくらくらしてくる.



ところで, Hewlett PackardのHP16Cが市販されてから, 八進法, 十六進法の計算はもっぱらHP16Cを利用している.

HP16C