3

データベースに出入りした後、2 桁の 10 進数が余分な 0.000000000000000001 (またはその程度) を取得することについて少し混乱しています。

これは私がやったことです:(Rails 3.2.8)

移行を作成しました:

class CreateItems < ActiveRecord::Migration
  def change
    create_table :items do |t|
      t.column :price, :decimal, :precision => 16, :scale => 2
    end
  end
end

モデルを作成しました:

class Item < ActiveRecord::Base
end

それで:

$ rails c
>> i = Item.new
>> i.price = 9.46
>> i.save
>> Item.first.price
=> #<BigDecimal:46b3768,'0.9460000000 000001E1',27(45)>

これは SQLite データベースであり、すべて問題ないように見えます。

$ rails db
>> select * from items;
1|9.46

これが発生していることに気付いた唯一の数値は 9.46 であることに注意してください。余分な 0.00000000000001 はどこから来たのですか?


編集一部の数値の浮動小数点表現は、小さなエラーがなければ不可能であることを理解しています。しかし、なぜItem.first.price等しくないのBigDecimal.new('9.46')でしょうか? SQLite は、整数ではなく浮動小数点数を格納していて、それを 10 で割る必要がある回数を格納していますか (これは、10 進数の列に期待されることです)。または、DB から値を取得する際に気付いていない ActiveRecord の落とし穴がありますか? 下記参照:

$ rails c
>> decimal = BigDecimal.new('9.46')
>> Item.first.price == decimal
=> false
4

3 に答える 3

1

double9.46は、IEEE精度の浮動小数点数として正確に表すことはできません。これは非常に多くの結果をもたらしますが、ここでは、正確に表現可能で、入力したものに最も近い値を取得していることを意味します。

9.46' 'を取り出すことが重要な場合は、TEXT親和性のある列に格納します(そして、「数値」ではなく文字列を格納していることに注意してください)。

于 2012-10-09T22:07:30.807 に答える
1

この記事を読むことをお勧めします:すべてのコンピューター科学者が浮動小数点演算について知っておくべきこと

記事の tl;dr バージョン...

無限に多くの実数を有限数のビットに圧縮するには、近似表現が必要です。無限に多くの整数がありますが、ほとんどのプログラムでは、整数計算の結果を 32 ビットで格納できます。対照的に、ビット数が固定されている場合、実数を使用したほとんどの計算では、その数のビットを使用して正確に表現できない量が生成されます。したがって、浮動小数点計算の結果は、その有限表現に適合させるために丸めなければならないことがよくあります。この丸め誤差が浮動小数点演算の特徴です。

于 2012-10-09T22:08:30.213 に答える
1

私はルビーにあまり詳しくありませんが、使用する代わりに

i.price = 9.46

使ってみて

i.price = BigDecimal.new('9.46')
于 2012-10-09T22:08:50.383 に答える