gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 04:03:57 27 4
gpt4 key购买 nike

有时,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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com