ActiveRecord 中的浮点数与十进制数 [英] Float vs Decimal in ActiveRecord

查看:20
本文介绍了ActiveRecord 中的浮点数与十进制数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Sometimes, Activerecord data types confuse me. Err, often. One of my eternal questions is, for a given case,

我应该使用 :decimal 还是 :float?

Should I use :decimal or :float?

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

I've often come across this link, ActiveRecord: :decimal vs :float?, but the answers aren't quite clear enough for me to be certain:

我见过很多人建议完全不要使用的线程浮动并始终使用十进制.我也看到了一些人的建议人们只将浮动用于科学应用.

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、...
  • Geolocation/latitude/longitude: -45.756688, 120.5777777, ...
  • Ratio/percentage: 0.9, 1.25, 1.333, 1.4143, ...

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

I have used :decimal in the past, but I found dealing with BigDecimal objects in Ruby was unnecessarily awkward as compared to a float. I also know I can use :integer to represent money/cents, for example, but it doesn't quite fit for other cases, for example when quantities in which precision could change over time.

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

推荐答案

我记得我的 CompSci 教授说过永远不要使用浮点数作为货币.

I remember my CompSci professor saying never to use floats for currency.

原因在于 IEEE 规范如何以二进制格式定义浮点数.基本上,它存储符号、分数和指数来表示浮点数.它就像二进制的科学记数法(类似于 +1.43*10^2).因此,不可能在 Float 中准确存储分数和小数.

The reason for that is how the IEEE specification defines floats in binary format. Basically, it stores sign, fraction and exponent to represent a Float. It's like a scientific notation for binary (something like +1.43*10^2). Because of that, it is impossible to store fractions and decimals in Float exactly.

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

That's why there is a Decimal format. If you do this:

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.

So if you are dealing with small fractions, like compounding interests, or maybe even geolocation, I would highly recommend Decimal format, since in decimal format 1.0/10 is exactly 0.1.

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

However, it should be noted that despite being less accurate, floats are processed faster. Here's a benchmark:

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 位有效数字.这在权衡准确性和速度方面很有用.因为他们不需要像速度一样的精度,所以他们会使用浮点数.

Answer

Use float when you don't care about precision too much. For example, some scientific simulations and calculations only need up to 3 or 4 significant digits. This is useful in trading off accuracy for speed. Since they don't need precision as much as speed, they would use float.

如果您处理的数字需要精确并求和为正确的数字(例如复利和与金钱相关的事物),请使用十进制.记住:如果你需要精度,那么你应该总是使用十进制.

Use decimal if you are dealing with numbers that need to be precise and sum up to correct number (like compounding interests and money-related things). Remember: if you need precision, then you should always use decimal.

这篇关于ActiveRecord 中的浮点数与十进制数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆