指数・対数関数を使うと加減算と剰余算が往復出来ます。
#剰余算が指数関数では添字上の加減算に置き換えられる。
> 8*32
[1] 256
> 2^3
[1] 8
> 2^5
[1] 32
> 2^(3+5)
[1] 256
> 2^(8)
[1] 256
この考え方を応用すれば指数・対数関数(Exponential/Logarithmic Function)の計算を配列の検索に置き換えられるのです。近世以降の科学計算の急発展に欠かせなかった「対数表」概念の登場ですね。
#配列が整数を直接扱えないので工夫
a0<-array(1:121,dim=c(11,11))
i0<-c(1:11)
c0<-seq(-5,5,length=11)
for (i in i0){
a0[i,]<-2^(c0+(i-6))
}
#-5~0~5を1~11に変換
Ind<-function(x){x+6}
#計算を配列検索に置き換える関数
Culc2<-function(x,y){
a0[Ind(x),Ind(y)]
}
実際の計算例
> a0
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 0.0009765625 0.001953125 0.00390625 0.0078125 0.015625 0.03125 0.0625 0.125
[2,] 0.0019531250 0.003906250 0.00781250 0.0156250 0.031250 0.06250 0.1250 0.250
[3,] 0.0039062500 0.007812500 0.01562500 0.0312500 0.062500 0.12500 0.2500 0.500
[4,] 0.0078125000 0.015625000 0.03125000 0.0625000 0.125000 0.25000 0.5000 1.000
[5,] 0.0156250000 0.031250000 0.06250000 0.1250000 0.250000 0.50000 1.0000 2.000
[6,] 0.0312500000 0.062500000 0.12500000 0.2500000 0.500000 1.00000 2.0000 4.000
[7,] 0.0625000000 0.125000000 0.25000000 0.5000000 1.000000 2.00000 4.0000 8.000
[8,] 0.1250000000 0.250000000 0.50000000 1.0000000 2.000000 4.00000 8.0000 16.000
[9,] 0.2500000000 0.500000000 1.00000000 2.0000000 4.000000 8.00000 16.0000 32.000
[10,] 0.5000000000 1.000000000 2.00000000 4.0000000 8.000000 16.00000 32.0000 64.000
[11,] 1.0000000000 2.000000000 4.00000000 8.0000000 16.000000 32.00000 64.0000 128.000
[,9] [,10] [,11]
[1,] 0.25 0.5 1
[2,] 0.50 1.0 2
[3,] 1.00 2.0 4
[4,] 2.00 4.0 8
[5,] 4.00 8.0 16
[6,] 8.00 16.0 32
[7,] 16.00 32.0 64
[8,] 32.00 64.0 128
[9,] 64.00 128.0 256
[10,] 128.00 256.0 512
[11,] 256.00 512.0 1024
>
#関数のテスト例
> 2^(0+0)
[1] 1
> Culc2(0,0)
[1] 1
> 2^(0+1)
[1] 2
> Culc2(0,1)
[1] 2
> 2^(0+2)
[1] 4
> Culc2(0,2)
[1] 4
> 2^(0+3)
[1] 8
> Culc2(0,3)
[1] 8
>
> 2^(1+0)
[1] 2
> Culc2(1,0)
[1] 2
> 2^(1+1)
[1] 4
> Culc2(1,1)
[1] 4
> 2^(1+2)
[1] 8
> Culc2(1,2)
[1] 8
> 2^(1+3)
[1] 16
> Culc2(1,3)
[1] 16
#常用対数表(Table of Common Logarithms)
近世には、それまで人類が馴染んできたLog10の対数表を使った計算システムが発達しました。ここでは当時の考え方の再現を試みます。せっかくなのである意味当時のそうした努力を起源とするコンピューターを駆使して。我々が親しんでいる「カーネルのメインループが全てを制御するコンピューター」登場前夜のエピソード……
ジョン・ネイピアが20年かけた対数表について - Qiita
大航海時代の航海術にはサインやコサインの三角法が必須で、三角法も有効数字が10桁以上もある精密なものが作られていましたが、その計算、特にかけ算と割り算が困難を極めたのです。1590年に、ネイピアの友人がある事情でデンマークに行き、ティコ・ブラーエの天文台を見ました。そこで三角法の式を利用して積を和に直す方法(積和の公式)が使われていることを知りネイピアに伝えたところ、彼はこの話に刺激されて対数の研究を始めたそうです。
三角関数は直角三角形に対して考えられる6種類の比の間の関係を扱う三角法がその起源で、角度に比の値を対応させる6種類の関数です。三角法は英語ではtrigonometry といい、三角形の測量という意味です。四千年前の古代エジプトで、すでにその萌芽が見られ、バビロニアやギリシアの天文学にもその考え方が見られます。6世紀インドで書かれた『アールヤバティーヤ』という本は様々な角度の正弦(sin)値を計算する方法を述べており、はっきりと三角関数としてとらえられています。インドの三角関数がアラビア経由でヨーロッパに伝わったと考えられており、現在使われているsin、cos、tanといった表記法はヨーロッパで考え出されました。
我が国にはオランダ語の数学書・天文学書や中国に伝わったヨーロッパの数学や天文学の漢訳書(『崇禎暦書』など)を通じて伝わりました。主に天文計算、測量術、航海術で使われ、ヨーロッパの物理学の本に頻出します。三角関数は角度に数字を対応させる関数ですから、角度の概念がないと生まれません。ところが、和算では角度の概念がありませんでした。方角は十二支に対応させて示していましたが、数値化はされていないので、中間の方角を正確に表現できません。角度が使われたのは、天文、測量、航海術の分野においてのみでした。
我が国での最初の三角関数表は建部賢弘(1664年〜1739年)の『算暦雑考』であるといわれます。建部賢弘は円周率の計算を行ったことで有名ですが、その数値を用いて1度毎に(1/2)sin x の値を小数点以下11桁まで計算した半弦表を作りました。建部は1度を1限と呼んでおり、直径が1尺の円で計算しましたので、半弦の長さが(1/2)sin x尺となっています。これに基づいて半背(弧)、矢、半弦の長さを1限おきに計算した表を作りましたが、この本は佐藤健一『建部賢弘の「算暦雑考」(1995年)』に復刻されています。
我が国で実際に使われた三角関数表はヨーロッパの三角関数表を漢訳したもので、割円八線表と呼ばれました。八線とは正弦(sin x)、余弦(cos x)、正割(sec x=1/cos x)、余割(cosec x=1/sin x)、正接(tan x=sin x/cos x=sec x/cosec x)、余接(cot x=1/tan x=cos x/sin x=cosec x/sec x)、正矢(1-cos x)、余矢(1-sin x)の8つの総称。角度の単位は直角を90度としますが、1度を60等分してそれを1分とした表と1度を100等分してそれを1分とした表の2種類があります。森正門の『割円表(1857年)』は1度を60分としていますが、渋川景佑(1787年〜1856年)の『新法暦書 続編(1846年)』では1度を100分としています。また割円八線表は日本地図作成で有名な伊能忠敬(1745年〜1818年)が測量時に携帯していたことでも有名です。
天文学では球面三角法を利用するので、三角関数の掛け算が多く出てきます。この掛け算を足し算に変える三角関数の対数表も作られており、この表も我が国に輸入され、紹介されました。また、三角関数表は円を三等分する弦の長さを求める時に出てくるsin x = ax+b のような超越方程式を解く場合に必要になります。
対数表はJ. Napier(1550年〜1617年)が作り上げた数表で、掛け算を足し算に変えてしまうための表です。このアイデアは桁数の大きい計算が必要となる、航海術や天文計算を簡単に行うため考えだされました。10x=pの逆関数log10p=xのことをpの「常用対数」と呼び、pに対応するxの値を表にしたものを「常用対数表」と呼びます。
この方法が便利であるのは1,034×2,213×3,256×4,378のように掛け算を何度も繰り返す計算がlog10(1,034)+log10(2,213)+log10(3,256)+log10(4,378)という足し算に置き換わることです。
特に桁数の多い三角関数の値同士の掛け算が必要になる天文計算や測量術での利用のため三角関数の対数表x↦log10sin x も作られました。この表を使うと、球面三角法でよく出てくるsinα×sinβ×sinγのような計算を足し算に変えることができます。
(対数表に関する)正確な答を求めるには、1.000001のようにもっとずっと1に近い数の累乗が必要となる。そうすると表がはるかに長くなり、累乗の数が100万個などになってしまう。その表を作るための計算は、とてつもない大事業となる。しかし1回だけやればいい。誰か自分を犠牲にする恩人が最初にその努力を割いてくれれば、その後の世代は大量の計算をしなくて済むようになるのだ。
ジョン・ネイピア「素晴らしき神の数表解説(MIRIFICI Logarithmorum Canonis descriptio、1614年)」序文
数学的手法を実践している仲間の数学者にとって何よりうんざりするのは、長々しい掛け算や割り算、比の計算、平方根や立方根の開平など、……うっかりした間違いをたくさん起こしかねない退屈な作業に煩わされて、大幅に遅れることである。そこで私は発想を転換し、確実で手早い手法によってこれらの面倒を改善できるかもしれないと考えた。そしてあれこれ考えた末にようやく、その手順を短縮する驚きの方法を見つけた。……数学者に広く使ってもらうための手法を発表するというのは、愉快な仕事である。
当時はこうした決意の産物として数十年の歳月を費やして行われた事業が、現代のコンピューターに処理させると一瞬…
#常用対数表(Table of Common Logarithms)の作成
Ind00<-c(seq(1.0,10.0, by = 0.01))
Log00<-c(round(log10(Ind00),digits =4))
ToCL00<-data.frame(Numbers=Ind00,Log10=Log00)
plot(ToCL00,type="S",main="Table of Common Logarithms")
#この表を使って実際に計算してみる。例えば1.43×5.93。まずは計算結果を確認。
1.43*5.93
[1] 8.4799
#とりあえずlog10(1.43)を求める。Numbersに1.43が収録されてる列から0.1553が取り出される。
> ToCL00[ToCL00$Numbers==1.43,2]
[1] 0.1553
#次いで log10(5.93)を求める。Numbersに5.93が収録されてる列から0.7731が取り出される。
> ToCL00[ToCL00$Numbers==5.93,2]
[1] 0.7731
#0.1553と0.7731を合計すると0.9284。とりあえずこれに最も近い最小の数字を答えとしてみると8.48が得られる。
> 0.1553+0.7731
[1] 0.9284
> Results00<-ToCL00[ToCL00$Log10>=0.9284,1]
> Results00[1]
[1] 8.48
Rによる直接計算(掛け算→足し算)
> 1.43*5.93
[1] 8.4799
> log(1.43,base=10)
[1] 0.155336
> log(5.93,base=10)
[1] 0.7730547
> log(1.43,base=10)+log(5.93,base=10)
[1] 0.9283907
> 10^0.9283907
[1] 8.479899
pythonによる直接計算(掛け算→足し算)
import numpy as np
print(1.43*5.93)
print(np.log10(1.43))
print(np.log10(5.93))
a=np.log10(1.43)+np.log10(5.93)
print(a)
print(10**a)
#出力結果
8.479899999999999
0.1553360374650618
0.7730546933642626
0.9283907308293244
8.4799
Rによる直接計算(割り算→引き算)
> 1.43/5.93
[1] 0.2411467
> log(1.43,base=10)
[1] 0.155336
> log(5.93,base=10)
[1] 0.7730547
> log(1.43,base=10)-log(5.93,base=10)
[1] -0.6177187
> 10^-0.6177187
[1] 0.2411467
pythonによる直接計算(割り算→引き算)
import numpy as np
print(1.43/5.93)
print(np.log10(1.43))
print(np.log10(5.93))
a=np.log10(1.43)-np.log10(5.93)
print(a)
print(10**a)
#出力結果
0.2411467116357504
0.1553360374650618
0.7730546933642626
-0.6177186558992007
0.24114671163575047
実践例その2(1034*2213=2288242)
#次は1,034×2,213を計算してみる。こちらもまずは計算結果を確認。
1034*2213
[1] 2288242
#「手計算」には人間に理解しやすくするテクニックが盛り込まれている。まずはlog10(1034)を求めよう。
log10(1034)
[1] 3.014521
#log10(10)=1, log10(100)=2,log10(1,000)=3, log10(10,000)=4だから、まずはlog10(3+1.034)の形に変換。
round(log10(1034), digit=0)
[1] 3
#さらに1.034を1.03に丸める事でNumberに1.03が収録されてる列のLog10から0.0128が取り出せる。合計すると3.0128。
> ToCL00[ToCL00$Numbers==1.03,2]
[1] 0.0128
> 3+0.0128
[1] 3.0128
#次いで log10(2213)を求める。
log10(2213)
[1] 3.344981
#同様にまずはlog10(3+2.213)の形に変換。さらに2.213を2.21に丸めるとNumbersに2.21が収録されている列から0.3444が取り出せる。合計すると3.3444。
> ToCL00[ToCL00$Numbers==2.21,2]
[1] 0.3444
> 3+0.3444
[1] 3.3444
#そして3.0128と3.3444を合計すると6.3572となる。
> 3.0128+3.3444
[1] 6.3572
#log10(1,000,000)=6を分離。表上で残りの0.3572以上の最小の数字が2.28なので得られる答えは2.28の10の6乗、すなわち2,280,000となる。
> Results00<-ToCL00[ToCL00$Log10>=0.3572,1]
> Results00[1]
[1] 2.28
>2.28*10^6
[1] 2280000
> 10^6.3572
[1] 2276145
Rによる直接計算直接計算(掛け算→足し算)
> 1034*2213
[1] 2288242
> log(1034,base=10)
[1] 3.014521
> log(2213,base=10)
[1] 3.344981
> log(1034,base=10)+log(2213,base=10)
[1] 6.359502
> log(1034*2213,base=10)
[1] 6.359502
> 10^6.359502
[1] 2288242
pythonによる直接計算(掛け算→足し算)
import numpy as np
print(1034*2213)
print(np.log10(1034))
print(np.log10(2213))
a=np.log10(1034)+np.log10(2213)
print(a)
print(10**a)
#出力結果
2288242
3.0145205387579237
3.344981413927258
6.359501952685182
2288242.000000003
Rによる直接計算(割り算→引き算)
> 1034/2213
[1] 0.467239
> log(1034,base=10)
[1] 3.014521
> log(2213,base=10)
[1] 3.344981
> log(1034,base=10)-log(2213,base=10)
[1] -0.3304609
> log(1034/2213,base=10)
[1] -0.3304609
> 10^-0.3304609
[1] 0.467239
pythonによる直接計算(割り算→引き算)
import numpy as np
print(1034/2213)
print(np.log10(1034))
print(np.log10(2213))
a=np.log10(1034)-np.log10(2213)
print(a)
print(10**a)
#出力結果
0.46723904202440125
3.0145205387579237
3.344981413927258
-0.3304608751693343
0.4672390420244012
*よく「人類は指数より先に対数を発見した」と言われるが、実は対数化した数字の計算を元の10進数に戻す「逆引き」の段階で既に暗示的に指数概念を駆使していたりする。まさに「発見」とは何か問われる事例…
壮絶な桁あふれとの戦い…人間にとって分かりやすい算出方法と数理モデル上の適正アルゴリズムとの衝突…そして最初期のコンピューターはまさに「機械化による対数表の精度向上」を図って創造されたのです。
「コンピューターの時代」が人類に与えた影響は?
チャールズ・バベッジは機械式の自動計算機としては非常に大規模なものを設計し制作。1833年には数表作成用の階差機関の開発からより汎用的な解析機関へと興味を移したが、この時にジャカールのパンチカードをプログラムの表現に使った(ジャカード織機では、カードの穴は経糸の上げ下げを直接示すだけだが、これはコード化である)。
1835年に記されたその解析機関についての記述によれば汎用のプログラム可能なコンピュータであり、入力にはパンチカード、動力源には蒸気機関を採用し、歯車や軸の位置で数値を表すものとされている。元々は対数表を高精度で作成することを目的としていたが、すぐにそれ以外の用途にも使える汎用プログラム可能コンピュータとして構想を発展させたが、機械製作を担当した職人との不和など様々な要因が重なって頓挫。プロジェクトへのイギリス政府の出資も中止となった。
ちなみにこの頃、ジョージ・ゴードン・バイロンの娘エイダ・ラブレスがFederico Luigi, Conte Menabrea の著した "Sketch of the Analytical Engine" を英訳し、大量の注釈を付記している。これが世界初のプログラミングについての出版物とされる。またダブリン出身の会計士 Percy Ludgate はバベッジの業績を知らなかったが、独自にプログラム可能なコンピュータを設計し、1909年に出版した著作にそれを記している。
それにつけても、どうしてコンピューターの発達速度は現代に近くほど急加速するのか。そのヒントは以下の様な「障害」の消滅にある様で、この事が話をややこしくさせるのでした。
ゼロックスの「Alto」は、なぜ成功できなかったのか──パソコンの歴史を決定づけたプレゼンの舞台裏
ゼロックス社長のデヴィッド・カーンズは、のちにアルトのプレゼンテーションを「テクノロジーの祭典」と呼び、「テクノロジーの未来を見たと誰もが口々に言っており、非常に印象深かった」と振り返っている。だが、プレゼンテーションを終えたPARCのチームは、幹部のそんな熱意などまったく感じなかった。
それどころか、その場で実際に体験できる時間を設けた際、アルトの前に座ってキーボードを操作し、マウスを試していたのは、ゼロックスの幹部ではなく彼らの妻たちだった。キーを打つのは女性事務員の仕事と考えているらしい夫たちは心を動かされた様子もなく、腕組みをして会場の端から遠巻きに眺めているだけだった。
研究員のひとりは、ある幹部役員がこう言ったのを耳にしている。「男であんなに早くキーを打てる人間は見たことがないな」。つまり、明らかに目のつけどころを間違えていたのだ。
世界初のSF映画「月世界旅行(Le Voyage dans la Lune,1902年)」が示した「映画におけるサイエンス・フィクション」の可能性を飛躍的に向上させたSF映画黎明期の傑作とされるモノクロサイレント映画「メトロポリス(Metropolis,1926年製作,1927年に公開)」を手掛けたフリッツ・ラング監督は、脚本を担当した妻のテア・フォン・ハルボウがそれを出版した際、序文で「(もっとちゃんとした形で)機械と人間の関係について語られるべきだったかもしれない」と不満を漏らしています。私はこれをカート・ヴォネガット・ジュニアが「ローズウォーターさん、あなたに神のお恵みを(God Bless You, Mr.Rosewater,1965年)」の冒頭「蜜蜂にとって蜂蜜(Honey)を主題とする物語が有り得る様に、人間にとってお金(Money)を主題とする物語が有り得る」とセットで覚えていて、「認識外を跋扈する絶対他者」へのイメージ力が枯渇しそうになる都度、思い返してきました。そう、見逃してはならないファクターは、しばしば完全に視野外に追いやられた時に最大の存在感を発揮するものなのです…
【追記】どうやら以下と同じ事を言ってる様だ?
群同型写像(Group Isomorphism)とは、与えられた2つの群の元の一対一対応(One-to-One Correspondence,全単射あるいは直積?)において、それぞれの群演算を両立する全単射関数である。2つの群の間に同型写像が存在すればそれは同型(Isomorphic)と呼ばれ、群論の見地からは同じ性質を持つとされ区別する必要がなくなる。
全単射 - Wikipedia
逆を言えば圏論などではより厳格に「同型=等しい」とは考えないという事みたいです。
射 (圏論) - Wikipedia
加法実数群$(\mathbb{R},+)$は、すべての正の実数が乗法についてなす群$(\mathbb {R}^+,×)$に、同型写像$f(x)=e^x(x \in \mathbb{R})$によって同型である:
(\mathbb {R},+) \cong (\mathbb{R}^{+},×)
加法整数群$(\mathbb {Z},+)$は加法実数群$(\mathbb{R},+)$の部分群であり、商群$\frac{\mathbb{R}}{\mathbb{Z}}$は、同型写像$f(x+\mathbb {Z})=e^{2πxi}(x \in \mathbb{R})$によって絶対値1の乗法複素数群$S^1$に同型である(ここでいうS^1とは1次元トーラスでもあるリー群$S_1$の事では?):
\frac{(\mathbb{R},+)}{(\mathbb{Z},+)} \cong S^1