(5) 5/15の授業内容:値の型変換

値の型について

前回利用したgetsメソッドはキーボードからの入力を文字列として取り込むメソッドであった。数字を入力した場合も文字として扱われてしまうため、このままでは計算を行うことができなかった。このため.to_iメソッドを利用して整数に変換する必要があった。

私たちは「123」は数字、「あいうえお」は文字であると直感的に理解をすることができるが、コンピュータは理解することができない。このため、取り扱う値が数字なのか文字列なのか、さらに厳密には整数なのか実数(整数+小数)なのかを指定してあげる必要がある。

直接入力による値の型の指定

a=10とプログラム中に記載した場合、aに10を代入するという意味になる。ではb=10.0と入力した場合はどうなるだろうか。c=3とし、d=a/c、e=b/cとした場合に何が異なるだろうか。まずは予想をしてから以下のプログラム(value.rb)を実行してみよう。

#!/usr/koeki/bin/ruby

a = 10
b = 10.0
c = 3
d = a / c
e = b / c
print d,"\n"
print e,"\n"

これを実行すると以下のようになる。

irsv{naoya}%ruby value.rb
3
3.333333333

a = 10とした場合、aに代入されている値は整数であると判断される。このため3で割っても小数点以下が切り捨てとなり、答えは3になっている。一方、b = 10.0とするとbに代入されている値は小数点以下を含む実数であると判断される。これにより3で割った答えにも小数点以下の値が含まれる。

出席課題

上記value.rbについて、下記の改良を加えて実行してみる。実行結果をメールに貼り付けて送る。

  • a = 30.0に変更する
  • e = b / cの下にf = "100"を追加
  • さらに1つ下の行にg = "200"を追加
  • さらに1つ下の行にh = f + gを追加
  • 一番下の行にprint h,"\n"を追加

制限時間は10分。完成しない場合は、途中まででも構わないので実行し、結果をメールで送ること。出席点は2点。提出要領は下記の通り。

  • 提出先:naoya@e.koeki-u.ac.jp
  • メールのSubject:学籍番号-ruby05
  • 本文の構成:1行目で学籍番号、氏名を記載する。2行目以降に結果を貼り付ける。わかったことがあればその下に記載する。

Tips:emacsでの日本語入力のオンオフはCtrl-oです

Tips:Mewによるメールの送り方はMewコマンドを参照

値の型変換(1):変換メソッド

3つの型変換メソッドについて

上記のようにあらかじめプログラムの中に数字を具体的に入力しておくことができるのであれば、プログラム作成時に配慮すれば、以後値の型について考える必要がない。ただし、キーボードからの入力を受け取るgetsメソッドを使用する場合は話が変わってくる。自分自身で入力をするのであれば注意すればよいが、一般ユーザーを対象にプログラムの開発を行う場合には、ユーザーが正しく値を入力するという期待は捨てた方が良い。この場合は、ユーザーがどのような値を入力しても対応できるようにプログラムを書いておく必要がある。

前回のプログラムで使用したto_iは、値の型を整数に変換するメソッドであったが、少数を使用する場合や数字を文字として使用する場合もある。値の型を変換する他のメソッドについても確認してみよう。

to_i:値の型を整数に変換する。小数点以下を含む値の場合は小数部は切り捨てになる

to_f:値の型を実数に変換する。小数点以下を含む数字を取り扱うことができるようになる

to_s:値の型を文字列に変換する。30は「さんじゅう」ではなく「さんぜろ」になるので数字の足し算や引き算はできなくなる

これらの働きをプログラムの実行を通して確認してみよう(form.rb)。

#!/usr/koeki/bin/ruby

print "足し算をします。1つ目の数字を入力してください:\n"
a = gets.chomp!   #=>100が入力されたとする
print "続けて2つ目の数字の入力をお願いします:\n"
b = gets.chomp!   #=>45が入力されたとする

c = a + b
print c,"\n"

d = a.to_i + b.to_i
print d,"\n"

e = a.to_f + b.to_f
print e,"\n"

f = a.to_s + b.to_s
print f,"\n"

これを実行すると以下のようになる。

irsv{naoya}%ruby form.rb
足し算をします。1つ目の数字を入力してください:100
続けて2つ目の数字の入力をお願いします:45
10045
145
145.0
10045

変換メソッドをつけずにa+bとした場合、getsは文字列として値を取り込むため、「100(いちぜろぜろ)」と「45(よんご)」の2つの値が入力されたことになり、これらの足し算をすると文字列が結合される。to_iやto_fをつけると数字として扱われることがわかる。

これらのメソッドをどこで使うか

キーボードから入力された数字を整数に変換する場合、gets.chomp!.to_iとすればよい。ただし、キーボードから数字以外の文字(例えばアルファベット)が入力される可能性がある場合、gets.chomp!.to_iとすると文字も整数に変換しようとする。「36(さんろく)」は整数に変換すると「36(さんじゅうろく)」になるが、「a」は整数に変換すると0になる。プログラムの中で「a」と入力することに重要な意味を持たせる場合には、0に変換されてしまうと都合が悪い。このため、入力される値がどのようなものであるのかに応じて、値の型変換メソッドをつける場所も変える必要がある。

例えば以下のプログラムでは、キーボードからaと入力されるとプログラムが終了する。しかし、digit = gets.chomp!.to_iとしているので、全ての入力は整数に置き換えられてしまう。aも0になってしまうので、if digit == "a"という条件を満たすことがなくなってしまう。

#!/usr/koeki/bin/ruby

while true
  print "今日の運勢を占います。0-9の好きな数字を入力してね(飽きたらaで終了)\n"
  digit = gets.chomp!.to_i
  if digit == "a"
    then break
  end
  
  if digit == 9
    print "最高についてます!\n"
  elsif digit > 5
    print "そこそこって感じですかね\n"
  else
    print "今日は家から出ない方がいいですよ\n"
  end
end

print "お疲れさまー\n"

このプログラムを改良し、.to_iをつける場所を変更すれば問題は解決する。

#!/usr/koeki/bin/ruby

while true
  print "今日の運勢を占います。0-9の好きな数字を入力してね(飽きたらaで終了)\n"
  digit = gets.chomp!
  if digit == "a"
    then break
  end
  
  if digit.to_i == 9
    print "最高についてます!\n"
  elsif digit.to_i > 5
    print "そこそこって感じですかね\n"
  else
    print "今日は家から出ない方がいいですよ\n"
  end
end

print "お疲れさまー\n"

値の型変換(2):printfを用いたフォーマット出力

printとprintfの使い分けはだいぶ理解できて来ただろうか。printは""内に入力されたメッセージをそのまま出力するメソッドである。一方、printfは変数内に代入されている値を出力する場合に""内に%dをいれ""の後ろに具体的に変数を指定することで、表示をおこなうメソッドであった。

ここで%dとは果たして何を意味しているのであろうか。実は%dは%dに分割することができる。厳密に言うと、%の位置に、""の後ろで指定された変数内の値を表示する。dは表示するときの形式(書式制御文字と呼ぶ)である。dはdecimal(10進数)の頭文字で、%dとした場合は変数内の値を「10進整数」で表示せよという意味になる。

我々が日常的に使用している数字は10進数と呼ばれるもので、0〜9の10種類の値を使用する。一方で、コンピュータの世界では0と1のみ使用する2進数、0、1、〜、9、a、b、c、d、e、fの16種類の数字を使用する16進数が利用されている。

printfで結果を出力する場合には、変数内の値を10進整数で表示する以外に、2進数や16進数、小数点を含む実数で表示することもできる。これにより、計算過程では.to_fをつけて計算を行ってきたが、結果を表示するときは小数点以下を切り捨てて整数で表示するというようなことも可能になる。主な書式制御文字は以下の通り。

  • d:10進整数の文字列に置き換える
  • b:2進整数の文字列に置き換える
  • x:16進整数の文字列に置き換える
  • f:浮動小数点数の文字列に置き換える
  • s:文字列に置き換える

なお、%と書式制御文字の間に出力幅を指定する整数を書くことができる。%4dのように「4」と入れると、結果を4桁で表示せよということになる。25(2桁)や137(3桁)の場合には、左側にそれぞれスペースが2つ、1つ空くことになる。整数の左にマイナスをつけると左づめになる。fの場合は6.2のように小数で指定する。これは全体の桁数が6桁で、小数点以下が2桁であるという指定になる。%fを桁の指定をせずに使用すると標準の6桁で表示される。

a = 100

printf ("10進整数だと%d\n", a)      #=>100
printf ("2進整数だと%b\n", a)       #=>1100100
printf ("16進整数だと%x\n", a)      #=>64
printf ("浮動小数点数だと%f\n", a)  #=>100.000000
printf ("文字列だと%s\n", a)        #=>100
整数を入れると右づめになる
printf ("答えは%6dです\n", a)    #=>___100

整数にマイナスをつけると左づめになる
printf ("答えは%-6dです\n", a)   #=>100___

%fでは全体の桁、小数部の桁の順に指定する
ここでは小数を含めて全体が6桁、小数は3桁になっている
printf ("答えは%6.3fです\n", a)  #=>_12.500

レポート課題

前回作成したregister.rbを以下の文章にしたがって改良しなさい。

今後消費税率がアップしそうな様子である。前回作成したregister.rbは内税方式であったが、内税方式ではいくら税金として支払っているのかがわかりづらい。そこで、外税方式に変更し、ユーザーが指定した(=キーボードから入力した)任意の税率(8.4%など小数を含む)を加えた会計金額を表示できるように改良しなさい(会計金額は小数点以下は切捨てとなる)。なお、税率はプログラム実行後、最初に指定するものとし、肉は8%、野菜は5%というように商品ごとに税率が変化する(商品の金額を入力するごとに税率を指定する)というのは今回はなしとする。さらに「お会計860円になります」「1000円お預かりいたします」「140円のお返しになります。どうもありがとうございました」というようなメッセージを追加しなさい(このためには支払い金額をユーザーに入力させる必要がある)。

今回のプログラムの改良は大きく分けると2つのポイントがある。(1)指定した消費税率で会計金額を表示する、(2)お会計のための金銭の授受の部分を追加する。両方の改良を行うことを求めているが、難しい場合はどちらか一方でも構わない。できる限り挑戦してみること。

  • 提出先:naoya@e.koeki-u.ac.jp
  • 提出期限:5/21(日)23:59(1限履修者)·5月28日(日)23:59(2限履修者)
  • メールのSubject:学籍番号-kadai03
  • 本文の構成:1行目で学籍番号、氏名を記載する。2行目以降は下記の構成とする
  1. 作成したプログラム
  2. プログラムの実行結果
  3. プログラムの説明
  4. 感想

  • 採点基準:期限内提出点(2点)、メールの体裁(1点)、プログラム(2点)、プログラムの説明(3点)
  • プログラムの説明は、プログラムの変更点について、今回学んだ値の型変換メソッドやprintfの書式制御文字に触れながら説明すること。触れていない場合は理解しているのかどうか判断できないため、減点する場合があります。
  • 説明に関して、文章の意味がわかりづらい場合や、Webページを単にコピー&ペーストしたものは減点することがある。一度読み直してから提出すること。
  • 驚異的に良くできているレポートについては満点の8点を超える得点をつけることがある。
  • よくできていたレポートは、他の人の参考になるよう、本人が特定できないような形で掲載する。掲載してほしくない場合はメールでの課題提出時にその旨記載すること。

Tips:emacsでの日本語入力のオンオフはCtrl-oです

Tips:ktermでのプログラムの実行結果をメールに貼り付けるには、コピーしたい箇所をマウスで選択し、emacs(Mew)上でマウスの真ん中ボタンをクリックする

Tips:Mewによるメールの送り方はMewコマンドを参照