皆さんは、『ミラーナンバー』と呼ばれる数値があるのをご存知でしょうか?
「121」や「1331」などの両端が同じ数字で挟まれていたり、真中で反転している数字をといいます。これらは中央で区切ったとき、鏡像関係にあり、左右対称になることからバランスが取れていて、縁起がいい数字だとも言われています。
鏡像関係といえば、『鏡の国のアリス』を思い出します。イギリスの児童文学作家で有名なルイス・キャロルが1871年に発表した小説で、アリスが鏡の中の世界を空想しているうちに、実際に鏡を通り抜けて鏡の世界に入り込んでしまうという物語です。
この作品では、鏡にうつる姿はこちらと同じように動くが,向こう側の構造は反対でもあるという「鏡像関係」が描かれています。
ところで、私が会社に入ってまもない1985年ごろ、会社である雑誌(*1)を購読しており、ある号で、「ミラーナンバーであり、かつ素数である数を出来るだけ多く求めなさい。」という懸賞問題がありました。当時、私はNECのPC-8001というパソコンで、BASIC言語のプログラムを組み、この懸賞問題を解こうとしました。
当時は1978年に発売された日立の「ベーシックマスター」をはじめ、家電メーカーから次々と家庭用のパソコンが登場し、シャープから「MZ-80K」、NECからは「PC-8001」が登場し、この3機種がパソコン御三家と呼ばれました。これらのパソコンを知っている人は相当パソコン歴が長いですね。どのパソコンも値段は私の初任給ぐらいだったと思います。
さて、過去にPC-8001で5桁の素数であるナンバーを求めたとき、結果を出すのに余りにも時間がかかり、途中で止めてしまいました。当時のパソコンはCPUが8ビット処理でしたので、扱える最大値は、2の16乗 = 32,767 の5桁です。最後までは行き着けなかったですが、そのとき得られた数値は26個で、計算時間は20日 ≒ 1,728,000秒でした。
一方、自宅で使っているパソコンで、同じ計算をすると、どのくらいの時間かかるか試しました。
- マクロはChatGPTを使ってエクセルのマクロ(VB)を作成
- パソコンは2014年のデスクトップ Core i3 メモリ8GB SSD 256GB OSはWindows10
結果:ミラーナンバーとなる素数の数と計算時間
5桁まで 108 個 0.1 秒
6桁まで 108 個 1.1 秒
7桁まで 776 個 27 秒
過去はROM-Basic、今回はエクセルのVBであり、細かい条件は全く無視しています。それを差し置いても、2014年の64ビットのパソコンは、1980年ごろの8ビットパソコンと比較して、約1,700万倍速度が上がっていました。性能が桁違いに向上し、相対的に値段は格段に下がっています。
CPUの性能については、最近発刊されたPCwatch 2024年1月29日の記事『PC向けCPUの相対性能』の図が参考になります。(*2)
「PC向けプロセッサは、50年あまりでおおよそ1億倍弱(7,000万倍ほど)高速化し、毎年1.445倍程度性能が向上している。」
最後に、ChatGPTへの質問式と、得られたマクロを載せておきます。
ChatGPTへの質問:
『「121」や「1331」などの両端が同じ数字で挟まれていたり、真ん中で反転している数値で、これをミラーナンバーといいます。エクセルで1桁から7桁までの素数で、かつミラーナンバーである数値をセルに表示するようなマクロを作ってください。』
ChatGPTから得られた回答:
『エクセルで VB(Visual Basic for Applications)を使用して、1 桁から 7桁までの素数でかつ、ミラーナンバーである数値をセルに表示するマクロを作成するためのサンプルコードを以下に示します。コードを実行するには、エクセルファイルで VBA エディタを開き、新しいモジュールを挿入し、そこに以下のコードを貼り付けてください。』(*3)
Sub FindMirrorPrimes()
Dim i As Long
Dim j As Long
Dim Starttime As Single
Dim startDigits As Long, endDigits As Long
Dim cell As Range
' マクロを実行するシートの設定
Set ws = ThisWorkbook.Sheets("Sheet1") ' シート名を適切なものに
' 1 桁から7 桁までの素数かつミラーナンバーである数を探す
Cells(1, 1) = "Number"
Cells(1, 2) = "Time"
Starttime = Timer
For i = 3 To 7
startDigits = 10 ^ (i - 1)
endDigits = (10 ^ i) - 1
For j = startDigits To endDigits
If IsPrime(j) And IsMirrorNumber(j) Then
' 該当するセルにミラーナンバーである素数を表示
Set cell = ws.Cells(ws.Rows.Count, 1).End(xlUp).Offset(1, 0)
cell.Value = j
' 該当するセルに計算に要した時間を表示
Set cell = ws.Cells(ws.Rows.Count, 1).End(xlUp).Offset(0, 1)
cell.Value = Round(Timer - Starttime, 2)
End If
Next j
Next i
End Sub
Function IsPrime(num As Long) As Boolean
Dim i As Long
If num < 2 Then
IsPrime = False
Exit Function
End If
For i = 2 To Sqr(num)
If num Mod i = 0 Then
IsPrime = False
Exit Function
End If
Next i
IsPrime = True
End Function
Function IsMirrorNumber(num As Long) As Boolean
Dim numStr As String
Dim reversedStr As String
' 数字を文字列に変換
numStr = CStr(num)
' 文字列を反転
reversedStr = StrReverse(numStr)
' 反転した文字列と元の文字列が一致するか確認
IsMirrorNumber = (numStr = reversedStr)
End Function
1)雑誌「MOL」(オーム社, 1963.4-1991.4)
2)https://pc.watch.impress.co.jp/docs/topic/feature/1562909.html
3)計算時間を表示するように、あとでルーチンを追加しています。