【結論】
・Rubyでは、整数同士の割り算をする場合、小数部分は切り捨てられる
・これは式内の数値が全てIntegerクラスであれば、
プログラム側は型変換を行わないので、返り値はIntegerになる為
・Integerクラスは整数を扱うクラスなので、小数は扱えない
・Integerクラスは、Rubyの組み込みライブラリによって定義されている
・なお、式内にIntegerクラスとFloatクラスが同時に存在する場合は、
より精度の高いFloatクラスが返り値に適用される
・Floatクラスは小数を扱うクラス
・やっぱりプログラミングは最高に面白い!!!!!!!
【本題】
スクールでは毎朝、知識の定着を図る為、練習問題を出してくれますが、
その中で腑に落ちるまで時間が掛かった問題があったので、今回それをまとめました。
====================================================
<問題>
対話型のインターフェイスで二桁の整数を入力すると、
十の位と一の位の数字に対して、足す、掛けるを行い、
最後にそれぞれの結果を足し合わせて出力するプログラムをrubyで作成してください。
※ターミナルの出力例
> 二桁の整数を入力してください
> 15
# 1 + 5と 1 * 5をそれぞれ計算
> 足し算結果と掛け算結果の合計値は11です
<模範解答(コード)>
def addition(a, b)
a + b
end
def multiplication(a,b)
a * b
end
def slice_num(num)
# 10の位
tens_place = (num / 10) % 10
# 1の位
ones_place = (num / 1) % 10
return tens_place, ones_place
end
puts "二桁の整数を入力してください"
input = gets.to_i
X, Y = slice_num(input)
add_result = addition(X, Y)
multiple_result = multiplication(X, Y)
puts "足し算結果と掛け算結果の合計値は#{add_result + multiple_result}です"
====================================================
私が引っ掛かったのは、入力した数値の10の位を、
「(num / 10) % 10」という計算式で求めているところです。
例えば、入力した数値が「25」だとすると、
「( 25 / 10 ) % 10」という計算式になり、返り値は「2」になって、10の位が分かるというものです。
但し、通常の数学のルールに則って計算すると、
①25÷10=2.5
②2.5÷10は整数で割れないから、余りは「2.5」(=返り値:2.5)
となる筈なので、返り値が「2」なる理由が初め理解できませんでした。
※上記の通り、Rubyの計算をいくつか試してみると、
「( 25 / 10 ) % 10 」は、返り値「2」
「25 / 10」は、返り値「2」
「2.5 % 10」は、返り値「2.5」
「25.0 / 10.0」は、返り値「2.5」
「25.0 / 10」は、返り値「2.5」となりました。
つまり、この結果から読み取れることは、
Rubyでは整数同士の計算だと、返り値は整数になるということです。
(小数が混じれば、返り値は小数になる)
・
・
・
「なんで小数が切り捨てられるんだ?」
ここで一旦そういうものと受け入れて、次に進めばよかったのですが、
どうにもモヤモヤしたので、色々調べました。
https://qiita.com/ryoff/items/0eb270fbc8de96cf158f
整数/整数=整数を返す仕様らしい。
・
・
・
「なんで、どういう原理?」「なんで、それで納得できるの??」
なんだか、ますます腑に落ちなくなったので、更に色々調べてみました。
https://prog.suke-blog.jp/entry/2018/07/14/170529#outline__2_2
整数はIntegerクラス、浮動小数点数はFloatクラスが対応しています。
・
・
・
「なるほど、このクラスが一つ噛んでいそうだな」
「あれ、Integerクラス・Floatクラスっていつ定義されたんだ?」
https://docs.ruby-lang.org/ja/latest/library/_builtin.html
組み込みライブラリは Ruby 本体に組み込まれているライブラリです。
このライブラリに含まれるクラスやモジュールは、 require を書かなくても使うことができます。
https://docs.ruby-lang.org/ja/latest/class/Numeric.html
組み込みライブラリ > Numericクラス
数値を表す抽象クラスです。Integer や Float などの数値クラス は Numeric のサブクラスとして実装されています。
・
・
・
「なるほど、組み込みライブラリのクラスだから初めから定義されているのね」
・
・
・
で、
「Integer クラス同士の計算結果が、整数になるのはなぜ?」
http://d.hatena.ne.jp/shuji_w6e/20070820
プログラム(コンピュータ)は小数への変換や分数を
原則としては自動変換しません
5÷2という計算をコンピュータにやらせる事は出来ますが、5ドルで2ドルの商品が幾つか買えるのか(期待する答えは2個)、5個のりんごを2人で分けるとき何個づつになるのか(期待する答えはのは2.5)という計算式が求められている条件はコンピュータは判断できないのです。
・
・
・
Integer ÷ Integer だと、プログラム側にはFloatの情報が届いていないわけだから、
わざわざFloatに変換する事なく、Integer で返しているという事か。
プログラム小数が必要と判断付かずに 整数で返って来たという事ね
「じゃあInteger ÷ Float でFloatが返って来たのはなんでだろうか?」
http://www9.plala.or.jp/sgwr-t/c/sec04.html
(2)式の中で行われる変換
式中で異なる型の定数や変数が現れたときは、精度の高い型に統一します。精度は今まで学習したものでは、下図のように char型 が一番低く、double型が一番高くなります。
・
・
・
どうやら型にも優先順位がある様で、Integer と Float が式内で同時に登場した場合は
より精度の高いFloat が返り値に適用されたわけだ(整数と小数なら、小数の方が情報量は多い)
ちなみに、これを「暗黙の型変換」というらしい。
以上、色々情報を組み合わせたツギハギだらけの答えですが、
とりあえず自分が納得するところに落ち着きました。
ここに至るのに、かなり時間を費やしてしまったので、仕様として割り切って、
さっさと次のステップに進んだ方が良かったかもしれないですが、
結果としてプログラミングの根本の動きを理解するいい機会になりました。
あと、答えを得るまでの、この論理を組み立てる過程が非常に楽しかったです
やっぱりプログラミングって
面白いですね!!!!!!!!
《今日の学習進捗》
データベース設計の基本的な内容(制約・正規化など)について学習。
今回のブログで取り上げた内容の調査で2時間くらい消費・・・
学習開始からの期間 :21日目
今日までの合計時間:195.0h
今日までに到達すべき目標時間:181.8h
目標との解離:+3.2h
「10,000時間」まで、残り・・・「9805時間!」