1
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

Ruby の "1101".to_i(2) は 2 進数を 10 進数に変換している,わけじゃない

Ruby の記事によく見られる誤りとしてこれがある。
本題に入る前に少し用語を整理しておこう。

まず

a = 17

という何の変哲もないプログラムを考える。
これはローカル変数 a数値 17 を代入している。
まず,この 17 のことを「数字」と表現した記事が非常に多い。

「数値」と「数字」は違う。(「数」と「数値」は基本的に同義1なので,この記事では区別しないことにする)

数字と言うのは,数を書き表すときに用いる記号のこと(ただし,負符号〔マイナス記号〕とか小数点などは数字に含めない)。
10 進法という記数法であれば,0 から 9 までの記号が「数字」だ。
上の例でいうと,ソースコード上の 17 は数字だが,a に代入されるのは数字ではなく数である。

非学術的な言語使用では比喩表現で数のことを「数字」と呼ぶことがある。
決算書を見て「いい数字が出たね」というように。
しかし,プログラミングの話をしているときは,数と数字をはっきり区別したい。

さて,本題に入ろう。

2 進法で「1101」と書かれた数は 10 進法ではどうなるだろう。
以下のプログラムで簡単に分かる。

p "1101".to_i(2) # => 13

答えは「13」。

このプログラムは String#to_i というメソッドを用いている。
文字列オブジェクトを整数オブジェクトに変換するものだが,引数で基数を指定することができる(基数というのは,N 進法の N のこと)。デフォルト値は 10 だ。
いまの場合,引数に 2 を与えているので,レシーバーの文字列を 2 進数とみなして整数オブジェクトを作る。

ここまではよいのだが,どうやらかなり多くの人がこの "1101".to_i(2) を見て「2 進数を 10 進数に変換している」と勘違いしているぽい。
いやまあ,誤解するのも無理はない。だって,上のプログラムを実行したら「13」て表示されるんだもんね。「13」は 2 進数「1101」に対応する 10 進数で間違いないもの。

ではいったい何が「誤り」だというのか?
もう一度「N 進法」「N 進数」という言葉について考えてみよう。
N 進法は N 種類の数字を用いる位取り記数法だ。記数法というのは数の表記方法のこと。
N 進数は N 進法に基づいて数を表したもの。

しかるに,to_i メソッドの返り値は文字列ではない。Integer オブジェクトだ。よって,「数字を並べたもの」ではない。2 進数でも 10 進数でもないのだ。だから to_i は「10 進数に変換するメソッド」ではない。

Integer オブジェクトは処理系内部では 2 進法に基づく表現となっているが,それは処理系の都合であって,ユーザーの知ったことではない2

では,一体なぜ上のプログラムは 10 進数の「13」を表示したのだろうか。
それは,こういう仕組みだ。

"1101".to_i(2) は 13 という数に対応する Integer オブジェクトを返す。
筆者がいま「13 という数」と書いたのは,とくに断りがない限り我々は数を 10 進法で表す習慣があるからそう書いたまでのこと。くどいようだが,この Integer オブジェクトは何らかの意味で「1」と「3」を並べたものでは断じてない。

さて,その Integer オブジェクトが p メソッドの引数として渡される。
p メソッドは,与えられたオブジェクトを inspect メソッドで文字列化して出力する。
Integerinspect メソッドは,引数を与えない場合,自身を 10 進法に基づく数字列(つまり 10 進数)という String オブジェクトに変換する。だから,今の場合,"13" という文字列が得られる。

要するに,to_i によって 10 進数に変換されたのではなく,それを表示するときに 10 進数になったというわけ。


  1. 「数の体系」とは言うが「数値の体系」とはあまり言わない気がする。「数値」は個々の具体的な一つの数について使われるとか,計算機の世界でよく使われる,といったことは言えそう。 

  2. 原理的には Integer オブジェクトを 10 進法に基づく内部表現で扱う Ruby 処理系があったっていいし(誰も作らんだろうけど),CRuby なんかが Integer を 2 進法に基づいて扱っているといっても,13 の内部表現が 1101 というビット列になっている,なんて単純なわけではない。 

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
1
Help us understand the problem. What are the problem?