有时,Activerecord 数据类型让我感到困惑。呃,经常。我永恒的问题之一是,对于特定情况,
我应该使用:decimal
or :float
?
我经常看到这个链接ActiveRecord::十进制与:浮点?,但答案还不够明确,无法让我确定:
我见过很多帖子,人们建议永远不要使用
浮动并始终使用小数。我也看到了一些人的建议
人们仅将浮点数用于科学应用。
以下是一些示例案例:
- 地理位置/纬度/经度:
-45.756688
, 120.5777777
, ...
- 比率/百分比:
0.9
, 1.25
, 1.333
, 1.4143
, ...
我用过:decimal
过去,但我发现处理BigDecimal
与浮动对象相比,Ruby 中的对象不必要地尴尬。我也知道我可以使用:integer
例如,表示金钱/美分,但它不太适合其他情况,例如精度可能随时间变化的数量。
- 使用每种方法的优点/缺点是什么?
- 有哪些好的经验法则可以帮助您了解使用哪种类型?
我记得我的 CompSci 教授说过永远不要使用浮动货币。
其原因在于IEEE 规范定义浮点数以二进制格式。基本上,它存储符号、分数和指数来表示浮点数。这就像二进制的科学记数法(类似于+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。
然而,应该指出的是,尽管精度较低,但浮点数的处理速度更快。这是一个基准:
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
Answer
Use float当你不太关心精度时。例如,一些科学模拟和计算最多只需要3或4位有效数字。这对于权衡准确性和速度很有用。由于他们对精度的要求不如对速度的要求,因此他们会使用浮动。
Use decimal如果您正在处理需要精确的数字并求和为正确的数字(例如复利和与金钱相关的事物)。请记住:如果您需要精度,那么您应该始终使用小数。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)