2010-08-18

2^64 (2 の 64 乗) って、どれぐらい?

現行の Mac に搭載されている OS、Snow Leopard は 64 ビット OS だと言われる。この 64 ビットって、いったいどれぐらいの数なんだろう?

64 ビットの「ビット」は 2 進数で 1 桁のこと。普段、わたしたちが日常生活で使う 10 進数では 1 桁で 0 〜 9 までの整数を表現できる。2 桁なら 99 まで、3 桁なら 999 まで、...。一般に、10 進 n 桁で 10n - 1 までの整数を表現できる。同様に、2 進 n 桁では 2n -1 までだ。つまり、64 ビットなら 264 - 1 が最大の数となる(符号なしの場合)。

では、この 264 (あるいは 264 - 1) って、いったいどれぐらいの大きさなんだろう?

(プログラマじゃない)普通の人々は 2 進数を扱うことがほとんどないから、2n と言われてもピンとこないだろう。いや、普通じゃない人(プログラマ)だって、28 や 216 ならともかく、264 の大きさは実感できない。わたしたちが数の大きさを実感するには、扱い慣れた 10 進数でなければならない。10 進数なら、桁を千、万、億、それに兆(英語ではちょっとスケールがずれるけど、thousand、million、billion、trillion といったところか)と読んでいくことで(それなりに)実感できる。

では、264 が 10 進数で何桁になるかを求めてみよう。それには「対数」を使う(底を10とする常用対数)。基本となるのは、(10進数で) n 桁の数 A に対して以下が成り立つこと。

10n-1 ≦ A < 10n ⇔ n-1 ≦ log10 A < n ...... (1)

つまり log10A が計算できれば、その桁数がわかる。今の場合、log10(264) を求めれば良いことになる。

さあ、受験数学を思い出しつつ、計算してみよう。

対数: 底の変換

計算に必要なのはこの公式だ。

logax = logbx / logba

この特別な場合として、b -> x (ただし x ≠ 1)とすれば、以下の公式も導ける。

logax = 1 / logxa

なぜ、底の変換を行うか、と言うと、264 に対して底が 2 の対数を求めることは簡単だからだ。対数の定義から、log2(264) というのは、2 を何乗すれば 264 になるか、という数のことだ。つまり、これは 64。一方で、log102 なら対数表に載っている。

これで材料がそろった。

log10(264) を計算する

底の変換公式と log102 ≒ 0.30103 (これは常用対数の対数表から読み取る) から、log10(264) の値を計算すると、

log10(264) = log2(264) / log210
= log2(264) * log102
≒ 64 * 0.30103
= 19.26592

この結果と式 (1) をあわせると、264 が(10進数で表すと) 20 桁の数になることがわかる。それより 1 少ないだけの 264 - 1 も同じく 20 桁の数だ。

ここまでは、紙と鉛筆があれば計算できる(log102 の値さえ覚えていれば)。けれど、20 桁の数とわかったところで、まだその大きさはピンとこない。

正確に計算するには……

もちろん、目の前にはコンピュータがあるんだから、正確に計算することもできる。これぐらい大きな数になると、多倍長整数演算とか、任意精度演算と呼ばれる機能が必要になる(64 ビット整数が扱えるなら、264 - 1 を計算できる)。

Ruby なら多倍長整数(Bignum)が組み込まれていて、かつ計算結果が固定長の整数(Fixnum)とシームレスにつながるから、こういう計算にはうってつけだ。

累乗の計算を素直に書くとこうなる。

(power.rb)
1: def power(m, n)
2:   if (n == 0)
3:     1
4:   else
5:     m * power(n - 1)
6:   end
7: end

これで power(2, 64) を計算させると、18,446,744,073,709,551,616 となる。確かに 20 桁の数だ。

追記@2010-11-29

ずっと後になって気付いたんだが、Ruby では累乗の計算に演算子が用意されている。それを使えば上のような関数を定義する必要はない。実行例を以下に示す。

[imac] mnbi% irb1.9
irb(main):001:0> 2 ** 64
=> 18446744073709551616

累乗の演算子に「**」を使うのは FORTRAN 由来かな? 「^」を使う表記の方が一般的じゃないか(・д・)?。

ちなみに、Snow Leopard (10.6.4) に標準で入っている Ruby (1.8.7 patchlevel 174) は 64 ビット用にコンパイルされていて、固定長の整数(Fixnum) でも 262 - 1 まで扱えるようだ(1 ビットは符号として、もう 1 ビットは何に使っているんだろう?)。これは (power(2,62)-1).class が Fixnum で (power(2,62)).class が Bignum になることから推測した。

数え上げるのにかかる時間

20 桁の数をながめていても、まだその大きさは実感できない。そもそも、どう読む?

1844 (京)
6744 (兆)
0737 (億)
0955 (万)
1616

4 桁ずつに区切るとこうなる。よって読み方は、「一千八百四十四京 六千七百四十四兆 (飛んで) 七百三十七億 (飛んで) 九百五十五万 一千六百十六」となる。いやいや、読めたって大きさはわからんわ。

そこで、1 から始めて、264 まで数えるのに必要な時間を考えてみる。子どもに戻ったつもりで、「い〜ち、に〜、さ〜ん、し〜、……」と数えたとする。1 秒に 1 つ数えられるとするなら(後の方になると大変だけど)、全部で 264 (= 18,446,744,073,709,551,616) 秒かかる。ということは、3600 秒で 1 時間、24 時間で 1 日、365 日で 1 年だから(うるう年は無視)、

18446744073709551616 seconds
-> 5124095576030431 hours
-> 213503982334601 days
-> 584942417355 years

584,942,417,355 年。要するに 5800 億年以上かかるってことだ。ヒトの寿命どころか、地球も太陽も、それどころか宇宙もまとめて寿命が尽きるぐらいの時間だ。

何のための計算か

264 を数えるのに 5800 億年以上かかることがわかったからといって何がうれしいのか?

今、仮に何らかのデータベースシステムを設計しているとしよう。レコード(データの単位)には ID を付ける。設計者としては ID を何ビットにするかを検討しなければならない。何ビットにすればこのシステムを長く使い続けることができるだろうか?

2n がどれくらいの数になるかがわかると、こんな問いに答えることができるようになる。ID が 16 ビットなら 65,536 個のレコードを作れる。32 ビットなら 4,294,967,296 個(約43億個)だ。64 ビットなら……今回計算したように約 1800 京個ほどになる。つまり、64 ビットの ID を持つデータベースなら、一人のユーザが毎秒一つのレコードを作ったとして、ID を使い切るのに 5800 億年以上かかるってことがわかるわけだ。ユーザが 100億人だとしても 58 年以上かかる。なので、64 ビットなら実際上、ID を使い切ることはまずないと確信を持てる。

「64 ビットは多すぎるだろう、32 ビットぐらいで十分だよ」と思うかもしれない。でも、Twitter の各 tweet につけられている ID はすでに 32 ビットの範囲を大きく超えている(2010年8月18日時点で 210 億以上になっている)。Twitter ぐらい大勢が毎日べったりと使うシステムになると 43 億個の ID を軽く消費してしまうわけだ。

関連リンク

0 件のコメント:

コメントを投稿