ruby-on-rails - ActiveRecord 中的浮点型与小数型

标签 ruby-on-rails types floating-point decimal rails-activerecord

有时,Activerecord 数据类型让我感到困惑。呃,经常。我永恒的问题之一是,对于特定情况,

Should I use :decimal or :float?

我经常遇到这个链接, ActiveRecord: :decimal vs :float? ,但答案还不够清晰,我无法确定:

I've seen many threads where people recommend flat out to never use float and always use decimal. I've also seen suggestions by some people to use float for scientific applications only.

以下是一些示例:

  • 地理位置/纬度/经度:-45.756688120.5777777、...
  • 比率/百分比:0.91.251.3331.4143、...

我过去曾使用过 :decimal,但我发现在 Ruby 中处理 BigDecimal 对象与 float 相比不必要地尴尬。例如,我还知道我可以使用 :integer 来表示金钱/美分,但它不太适合其他情况,例如当精度可能随时间变化的数量时。

  • 使用每种方法的优点/缺点是什么?
  • 有哪些好的经验法则可以帮助您了解要使用哪种类型?

最佳答案

我记得我的 CompSci 教授说过永远不要使用 float 货币。

原因是 IEEE specification defines floats以二进制格式。基本上,它存储符号、分数和指数来表示 float 。它就像二进制的科学记数法(类似于 +1.43*10^2)。因此,不可能在 Float 中精确存储分数和小数。

这就是为什么有十进制格式。如果您这样做:

irb:001:0> "%.47f" % (1.0/10)
=> "0.10000000000000000555111512312578270211815834045" # not "0.1"!

如果你这样做

irb:002:0> (1.0/10).to_s
=> "0.1" # the interprer rounds the number for you

因此,如果您要处理小分数,例如复利,甚至可能是地理定位,我强烈推荐十进制格式,因为在十进制格式中,1.0/10 恰好是 0.1。

但是,应该注意的是,尽管精度较低,但 float 的处理速度更快。这是一个基准:

require "benchmark" 
require "bigdecimal" 

d = BigDecimal.new(3) 
f = Float(3)

time_decimal = Benchmark.measure{ (1..10000000).each { |i| d * d } } 
time_float = Benchmark.measure{ (1..10000000).each { |i| f * f } }

puts time_decimal 
#=> 6.770960 seconds 
puts time_float 
#=> 0.988070 seconds

回答

当你不太关心精度时,使用float。例如,一些科学模拟和计算最多只需要3或4位有效数字。这对于权衡准确性和速度很有用。由于他们对精度的要求不如对速度的要求,因此他们会使用 float 。

如果您处理的数字需要精确并求和为正确的数字(例如复利和与金钱相关的事物),请使用小数。请记住:如果您需要精度,那么您应该始终使用小数。

关于ruby-on-rails - ActiveRecord 中的浮点型与小数型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8514167/

相关文章:

haskell - 如何从类型重建 Haskell 表达式

c - tan(x) = infinity 的不可能性证明(或反例),对于浮点值

ruby-on-rails - 门卫撤销 token

haskell - RankNType 内的约束

c++ - int 的大小是否取决于编译器和/或处理器?

math - float 学有问题吗?

java - 货币值的 Float 和 Double

javascript - rails : Click on results in Algolia search auto-completion

ruby-on-rails - 数据库之间的 Rake 任务复制

ruby-on-rails - 如何在删除:destroy in Rails?中传递ID