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

我应该用:decimal还是:float

我经常看到这个链接,100,但答案并不十分清楚,我无法确定:

我见过很多人建议不要直接使用的帖子

以下是一些例子:

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

我过go 用过:decimal个,但我发现用Ruby处理BigDecimal个对象比用float处理要尴尬得多.例如,我也知道我可以用:integer来表示货币/美分,但它不太适用于其他情况,例如精度可能随时间变化的数量.

  • 使用每种方法的优点/缺点是什么?
  • 要知道使用哪种类型,有什么好的经验法则?

推荐答案

我记得我的计算机科学教授说过永远不要使用浮动货币.

原因是IEEE specification defines floats是二进制格式的.基本上,它存储符号、分数和指数来表示浮点数.这就像是二进制的科学符号(比如+1.43*10^2).正因为如此,不可能准确地将分数和小数存储在浮点中.

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

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.

然而,应该注意的是,尽管浮动精度较低,但处理速度更快.以下是一个基准:

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个有效数字.这有助于在精度和速度之间进行权衡.因为他们不需要像速度那样精确,所以他们会使用浮动.

如果你处理的是需要精确的数字,并求和到正确的数字(比如复利和金钱相关的事情),请使用decimal.记住:如果你需要精度,那么你应该始终使用十进制.

Ruby-on-rails相关问答推荐

如何仅在所有配置/初始化器加载后才加载gem的Railites?

如何在Rails中创建没有字符串的查询

会话控制器中的某种问题

`ActionController::API` 祖先类在加载后不会更新

如何从数组中提取值

如何验证 Rails 中的多态字段关联?

rails select标签,预先 Select 了多个值

在 Rails 的 ActiveRecord 中,touch 有什么用?

如何获取 Ruby on Rails 生成的表单元素 id 以供 JavaScript 参考?

如何从 Rails 路由中删除控制器名称?

如何为 Rails SimpleForm Select 框设置默认 Select 值

Rails:设计:按角色登录后重定向

link_to 将参数与 url 一起发送并在目标页面上抓取它们

rails active admin 部署:找不到文件'jquery-ui'

如果多态关联的类型列不指向 STI 的基本模型,为什么多态关联对 STI 不起作用?

长期运行项目中的 Rebase Rails 迁移

Rails:为什么 with_exclusive_scope 受保护?关于如何使用它的任何好的做法?

Rails.cache 在测试之间被清除了吗?

在 Rails 3 中突出显示当前页面的最佳方法? -- 有条件地将css类应用于链接

为什么 rails bootstrap 这么慢,我该怎么办?