Webサイト制作コースのお申し込みはこちら Webサイト制作コースのお申し込みはこちら

Rubyにて数値計算をするうえで、複雑な計算をすることがあります。乱数の発生、平方根、sinやcosなどの三角関数・・・などなど。

Rubyではそれらを実装するためのクラスが提供されており、私たちはそれらのおかげで簡単に複雑な計算ができます。

数値計算といえば科学技術っぽく聞こえますが、もっと身近な例でいうと、金額計算も数値計算です。金額計算はお金の計算である以上、誤差や計算誤りは絶対に許されません。

では、Rubyではそのような厳密な計算はどうするのでしょうか?

本記事では、Randomクラスをはじめとした様々なクラス、端数処理、Ruby独特の分数計算を解説します。

Rubyの各種クラス、モジュール

様々なクラスが用意されていますが、まずは冒頭でふれた乱数(Ramdomクラス)から解説します。

Rubyの乱数クラス Random

乱数とは、何ら規則性がなく一定の範囲で均一に出る数値のことです。もう少しいうと、都度異なる数値かつ偏っていない(特定の数値ばかり出る確率が高いというのはダメ)数値のことです。

例えば「1から100までの範囲で乱数を発生させる」という場合です。

これを先ほどの解説に当てはめてみると「1つの値を連続して何度も取り出す。ただし、1から100までの間で、規則性がなく、確率的に偏りがないこと」となります。

これをRubyで実装するには、Randomクラスを使います。

puts Random.rand(100)

[実行結果]

※連続して何度も実行しています。

28

59

59

62

39

94

randメソッドの引数に100を与えたので、0から100より小さな整数がランダムに発生しました。引数を与えない場合は、ゼロから1より小さい値が返ります

Mathモジュール

三角関数や平方根など、数値計算でよく使うものはMathモジュールにて提供されています。

puts Math.sqrt(100)
puts Math.sin(Math::PI/2)

[実行結果]

10.0
1.0

結果の1行目は、100の平方根である10が返りました。2行目は、sin90度の1.0が返ってきました。

Mathモジュールには定数も提供されています。Math::PIで円周率πが得られます。それを1/2したからsin90度となったわけです。

Mathモジュールのより詳しい解説は、こちらをごらんください。

Rubyにおいても悩ましい端数処理

どの開発言語でも、端数処理は悩ましい問題です。

例えば、3,300円に消費税を加算した金額を計算しましょう。

puts 3300 * 1.08

[実行結果]

3564.0000000000005

「消費税計算は端数切り上げ」というルールがあると、ceilを使って以下の結果を出せます。

puts (3300 * 1.08).ceil

[実行結果]

3565

目的とする3564円より1円多く出ました!?金額計算でそれは致命的です。

Rubyでは、BigDecimalを使い以下のように対処します。

require "bigdecimal"
puts (BigDecimal("3300")*BigDecimal("1.08")).ceil

[実行結果]

3564

今度は正しく計算できました!

でも、なぜBigDecimalに文字列で値を渡さなければいけないのでしょうか?

では試しに普通に数値で渡しましょう。

どこでエラーになったのか分かるように、先ほどの計算をバラして試しましょう。

require "bigdecimal"

puts BigDecimal(3300)
puts BigDecimal(1.08)
puts BigDecimal(3300)*BigDecimal(1.08)
puts (BigDecimal(3300)*BigDecimal(1.08)).ceil

[実行結果]

(ファイル名):3:in `BigDecimal': can't omit precision for a Float. (ArgumentError)
    from 5473.rb:3:in `'

3行目で引数エラーがかかりました。

エラーメッセージを見ると、1.08と書いたとたんにFloat型のオブジェクトが生成されてしまい、それをBigDecimalに渡すと精度が落ちるということでした。

Rubyでの分数の計算 Rational

Rubyには、分数計算をするメソッドがあります。正確にいうと、有理数の計算を行うメソッドです。

有理数とは、分数で表せることができる数のことです。平方根や虚数などは、分数の形で表せないので無理数といいます。

ところで、以下の計算をしてみましょう。0.6と0.7を足すと1.3になりますので、trueが返るはずです。

a = 0.6
b = 0.7
c = 1.3

puts a + b == c

[実行結果]

false

こんな超単純な計算ですら正しい結果が出ないのは、Rubyのせいでしょうか?決してそうではなく、ここには浮動小数点に関する重要なテーマがあります。

かなり大事なことなので、じっくりと解説します。

人間の世界では、0.1は1/10、0.3は3/10と表せます。しかし浮動小数点は1/2、1/4、1/8・・・と2のべき乗の逆数で表現します。

0.5は1/2、0.25は1/4、0.75は1/2 + 1/4・・・と表現できるので問題ありません。では0.3はどうでしょうか?これは2のべき乗の逆数では表現できません。

がんばって0.3を2のべき乗で表現するとすると小数点以下が延々と続き、どこかで計算を打ち切らないといけません。

ここが誤差となって現れるわけです。これを丸め誤差といいます。

これに対処するにはどうすれば良いか、その解決策の1つとしてRationalを使う方法があります。

要は分母が2ではなく10であれば問題ありません。その考えをプログラムに載せましょう。

a = Rational(6,10) # 0.6を意味します
b = Rational(7,10) # 0.7を意味します
c = Rational(13,10) # 1.3を意味します

puts c == a + b

[実行結果]

true

今度は正しく計算できました!

念のためBigDecimalを使って同じことをしてみます。

require "bigdecimal"

a = BigDecimal("0.6") # 0.6を意味します
b = BigDecimal("0.7") # 0.7を意味します
c = BigDecimal("1.3") # 1.3を意味します

puts c == a + b

[実行結果]

true

BigDecimalでも正しく計算できました!

まとめ

本記事では、クラスを使った数値計算や端数処理を解説しました。

本記事の内容を自分で何度も試して、効率的かつ正確な数値計算ができるようになってくださいね!

エンジニアになりたい人に選ばれるプログラミングスクール「ポテパンキャンプ 」

ポテパンキャンプは卒業生の多くがWebエンジニアとして活躍している実践型プログラミングスクールです。 1000名以上が受講しており、その多くが上場企業、ベンチャー企業のWebエンジニアとして活躍しています。

基礎的な学習だけで満足せず、実際にプログラミングを覚えて実践で使えるレベルまで学習したいという方に人気です。 プログラミングを学習し実践で使うには様々な要素が必要です。

それがマルっと詰まっているポテパンキャンプでプログラミングを学習してみませんか?

卒業生の多くがWebエンジニアとして活躍

卒業生の多くがWeb企業で活躍しております。
実践的なカリキュラムをこなしているからこそ現場でも戦力となっております。
活躍する卒業生のインタビューもございますので是非御覧ください。

経験豊富なエンジニア陣が直接指導

実践的なカリキュラムと経験豊富なエンジニアが直接指導にあたります。
有名企業のエンジニアも多数在籍し品質高いWebアプリケーションを作れるようサポートします。

満足度高くコスパの高いプログラミングスクール「ポテパンキャンプ」

運営する株式会社ポテパンは10,000人以上のエンジニアのキャリアサポートを行ってきております。
そのノウハウを活かして実践的なカリキュラムを随時アップデートしております。

代表の宮崎もプログラミングを覚えサイトを作りポテパンを創業しました。
本気でプログラミングを身につけたいという方にコスパ良く受講していただきたいと思っておりますので、気になる方はぜひスクール詳細をのぞいてくださいませ。