Rubyで数値がどのように機能するか:整数、浮動小数点数、およびBigdecimalを理解する
Ruby2.4はFixnumをマージしました &Bignum 同じクラスに(Integer )ですから、Rubyのさまざまな数値タイプを確認する良い機会だと思います!
それがこの投稿で話し合うことです🙂
数値タイプの概要
まず、Rubyのすべての関連クラスのクラス階層を見てみましょう。
Numeric
Integer
Fixnum
Bignum
Float
Complex
Rational
BigDecimal (Standard Library)
ご覧のとおり、Numeric classは、すべての数値クラスの親です。 ancestorsを使用できることを忘れないでください 任意のクラスの親クラスを検出するメソッド。
例 :
Fixnum.ancestors - Fixnum.included_modules [Fixnum, Integer, Numeric, Object, BasicObject]
次に、これらのクラスを表形式で見てみましょう。
Fixnumの親クラス &Bignum | 1 |
| OS整数型(32ビットまたは64ビット)に適合する整数 | 1 |
| Bignum | 111111111111 |
| 5.0 | |
| (1 + 0i) | |
| (2/3) | |
| BigDecimal | 3.0 |
フロートの不正確さ
Float Rubyのクラスは、Rubyの公式ドキュメントでは「不正確」と説明されています。
なぜですか?
例を示しましょう :
0.2 + 0.1 == 0.3 # false
なぜこれが間違っているのですか?
0.2 + 0.1の結果を見てみましょう :
0.30000000000000004
丁度!それが不正確さの意味です。
これは、フロートの保存方法が原因で発生します。常に正確な10進数が必要な場合は、BigDecimalを使用できます。 クラス。
フロートとBigDecimal
BigDecimalは、任意精度の10進数を提供するクラスです。
例 :
require 'bigdecimal'
BigDecimal("0.2") + BigDecimal("0.1") == 0.3
# true
いつもBigDecimalを使ってみませんか それから?かなり遅いからです!
ここにベンチマークがあります :
Calculating -------------------------------------
bigdecimal 21.559k i/100ms
float 79.336k i/100ms
-------------------------------------------------
bigdecimal 311.721k (± 7.4%) i/s - 1.552M
float 3.817M (±11.7%) i/s - 18.803M
Comparison:
float: 3817207.2 i/s
bigdecimal: 311721.2 i/s - 12.25x slower
BigDecimal Floatより12倍遅い 、それがデフォルトではない理由です🙂
Fixnum vs Bignum
このセクションでは、Fixnumの違いについて説明します。 およびBignum Ruby2.4より前。
コードから始めましょう :
1.class # Fixnum 100000000000.class # Bignum
Rubyは私たちのために正しいクラスを作成し、それは自動的にFixnumをプロモートします Bignumに 必要に応じて。
注 :
Bignumを取得するには、より大きな数値が必要になる場合があります 64ビットのRubyインタープリターがある場合はオブジェクト。
なぜ異なるクラスが必要なのですか?答えは、大きな数値を処理するには別の実装が必要であり、大きな数値を処理するのは遅いため、Floatと同様の状況になるということです。 vs BigDecimal 。
Fixnumの特別な属性
Fixnum クラスにはいくつかの特別なプロパティもあります。たとえば、オブジェクトIDは式を使用して計算されます。
1.object_id # 3 20.object_id # 41
式は次のとおりです。(number * 2) + 1 。
ただし、Fixnumを使用する場合は、これだけではありません。 作成されているオブジェクトはまったくありません。 Fixnumに保存するデータはありません 、値はオブジェクトID自体から派生しているためです。
これは単なる実装の詳細ですが、知っておくと面白いと思います🙂
MRI(MatzのRuby Interpreter)は、次の2つのマクロを使用して、値とオブジェクトIDを変換します。
INT2FIX(i) ((VALUE)(((SIGNED_VALUE)(i))<<1 | FIXNUM_FLAG)) FIX2LONG(x) ((long)RSHIFT((SIGNED_VALUE)(x),1))>
ここで起こることは「ビットシフト」と呼ばれ、すべてのビットを左または右に移動します。
1つの位置を左にシフトすることは、2を掛けることと同じです。そのため、数式は(number * 2) + 1になります。 。 +1はFIXNUM_FLAGから取得されます 。
対照的に、Bignum 通常のクラスのように機能し、通常のオブジェクトIDを使用します:
111111111111111.object_id # 23885808
つまり、Fixnum Bignumの場合、オブジェクトはインタープリターレベルでどのように機能するかという点でシンボルに近いです。 オブジェクトは文字列に近いです。
2.4の整数
Ruby 2.4 FixnumとBignumは非推奨ですが、舞台裏では同じように機能します。
Rubyはあるタイプから別のタイプに自動的に切り替わります。
クラスを変更せずに 。
これは、小さなIntegerを意味します 数値は引き続きFixnumと同じように機能します 。
概要
この投稿では、Rubyに存在するさまざまな数関連のクラスについて学びました。
フロートが不正確であり、BigDecimalを使用できることを学びました 精度がパフォーマンスよりもはるかに重要である場合。また、Fixnum オブジェクトはインタプリタレベルでは特別ですが、Bignum は単なる通常のオブジェクトです。
この投稿がおもしろいと思ったら、下のフォームで私のニュースレターにサインアップすることを忘れないでください🙂
-
Ruby 2.6のMJITとは何ですか?どのように機能しますか?
Rubyのパフォーマンスはバージョンごとに大幅に向上しており、Ruby開発チームはRubyをさらに高速化するためにあらゆる努力をしています! これらの取り組みの1つは、3×3プロジェクトです。 目標は? Ruby3.0はRuby2.0の3倍高速になります 。 このプロジェクトの一部は、この記事のトピックである新しいMJITコンパイラです。 MJITの説明 MJITは「メソッドベースのジャストインタイムコンパイラ」の略です。 それはどういう意味ですか? RubyはコードをYARV命令にコンパイルします 、これらの命令はRuby仮想マシンによって実行されます。 JITはこれに別のレ
-
Rubyの配列クラスの使用方法(例+便利なメソッド)
アレイとは何ですか? 配列は組み込みのRubyクラスであり、0個以上のアイテムのリストを保持します 、およびこれらすべてのアイテムを簡単に追加、アクセス、およびループするのに役立つメソッドが含まれています。 配列が存在しない場合は多くの変数を使用する必要があるため、これは便利です。 例 : a =1b =2c =3 しかし、代わりに、あなたはそうすることができます : 番号=[1、2、3] 最良の部分は? 配列内には何でも入れることができます! いいね : 数字 文字列 より多くのアレイ! (それは多次元配列になります) アレイを最大限に活用できるように、アレイについ