こんにちは、masm11 です。
時々数学で遊んでみたくなりませんか? というわけで、今回は数学と戯れてみたいと思います。循環小数です。とは言え、ただ実証してみるだけですので、気楽にお付き合いいただければと思います。
循環小数とは
まず、循環小数とは何でしょうか?
見たまんま、循環している小数のことですね。
おそらく「」という書き方が曖昧で数学者の気に食わないのでしょう、これは以下のように書きます。
1 と 3 の上に点を付けて、「以下、1~3 の部分の繰り返しですよー」という意味です。正確です。
では、これを分数で表現してみます。
実は、
なのです。
もちろん、 の場合に限りません。
です。循環している部分を分子に書き、同じ桁数だけ 9 を分母に並べるのです。
ここまでは、もしかすると、「あ、高校の時にやった」という方もいらっしゃるかもしれません。
0.1 を2進数で正確に表現する
「そんなことできるの?w」 いえいえ、上記のように、循環小数を正確に表現できるのですから、できるかもしれません。
ここからは、10進数か2進数かを数値の右下に書きます。 は のことで、 は のことです。
では行きましょう。
ここまでは分数で2進数表記にしただけです。
10進数で分母を 999 の形にすればいいということは、2進数でも 111 の形にすればいいのかもしれません(*1)。
は ですね。これを の形にするにはどうすればいいでしょうか? 分母分子に何かを掛けましょう。, , , ... あ、 が ですね。では を掛けることにします。
最後の は、 を補っただけです。
さて、仮説 (*1) が正しいなら、
です。最後の分数は、 で割ってるだけなので、
となります。
さて、この値が10進数でいくつなのか、Ruby でコードを書いて確認してみました。
sig = 0.25 sum = 0 32.times do |i| mod = i % 4 sum += sig if [2, 3].include? mod puts sum sig /= 2 end
2進数の一桁ずつ、1 なら sum に加えて、0 なら加えない、それだけのコードです。 結果は以下のようになりました。
0 0 0.0625 0.09375 0.09375 0.09375 0.09765625 0.099609375 0.099609375 0.099609375 0.099853515625 0.0999755859375 0.0999755859375 0.0999755859375 0.0999908447265625 0.09999847412109375 0.09999847412109375 0.09999847412109375 0.09999942779541016 0.09999990463256836 0.09999990463256836 0.09999990463256836 0.09999996423721313 0.09999999403953552 0.09999999403953552 0.09999999403953552 0.09999999776482582 0.09999999962747097 0.09999999962747097 0.09999999962747097 0.09999999986030161 0.09999999997671694
に限りなく近くなっていますね。
0.1 の場合の実証としてはここまでです。
これで、おそらく正確に表現できたのでは、と思います。
一休み
2進数の小数が出てきたので、ついでに説明してみますと、
と、小数点より上が 1 になるように調整して、小数点より上を取り除き、 を浮動小数点の仮数部、 を指数部と呼びます (ただし、wikipedia によると、他にも方式があるようです)。
0.01 の場合
さて、0.1 を2進数で表現した結果はご存知の方も多かったのではないでしょうか。もう一つくらいやってみましょうか。0.01 です。
0.1 の場合と同様にここまで変形しました。 は です。これを何倍かして にしたいのです。
32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536
ここまでは頭に思い浮かべながら、違うことが想像できました。16bit 世代にはここらへんが限界です。この先は覚えていません。素直に Ruby の力を借りましょう。
n = 2 loop do break if (n - 1) % 25 == 0 n *= 2 end puts n puts (n - 1) / 25
出てきた答えは、
1048576 41943
これは、1M (メガ) ですね。これだけは最近ようやく覚えました。 です。 そして、上の出力結果の通り、 は だそうです。
では、分母分子を 倍しましょう。 なので、
これを 0.1 の場合と同様に Ruby のプログラムで検証します。
0 0 0 0 0.0078125 0.0078125 0.009765625 0.009765625 0.009765625 0.009765625 0.0098876953125 0.00994873046875 0.009979248046875 0.0099945068359375 0.0099945068359375 0.009998321533203125 0.009998321533203125 0.009999275207519531 0.009999752044677734 0.009999990463256836 0.009999990463256836 0.009999990463256836 0.009999990463256836 0.009999990463256836 0.009999997913837433 0.009999997913837433 0.009999999776482582 0.009999999776482582 0.009999999776482582 0.009999999776482582 0.009999999892897904 0.009999999951105565 0.009999999980209395 0.00999999999476131 0.00999999999476131 0.00999999999839929 0.00999999999839929 0.009999999999308784 0.009999999999763531 0.009999999999990905 0.009999999999990905 0.009999999999990905 0.009999999999990905 0.009999999999990905 0.00999999999999801 0.00999999999999801 0.009999999999999787 0.009999999999999787
綺麗に 0.01 に近づいてますね!
まとめ
0.01 ともなると、桁数が多くて、結局、途中の計算も検証も全て Ruby でやってしまいました。
なお、今回のこの記事では、理論的な裏付けなしに仮説 (*1) をでっち上げて使っています。 もし本気の用途に使われる際にはご注意ください。
ではまた!