首页 > 解决方案 > 如何在 Ruby 中将小数四舍五入到第一个有效数字

问题描述

我正在尝试解决与个人项目相关的任务的边缘案例。

它是确定一项服务的单价,由total_amount和组成cost

示例包括:

# 1
unit_price = 300 / 1000 # = 0.3

# 2
unit_price = 600 / 800 # = 0.75

# 3
unit_price = 500 / 1600 # = 0.3125

对于 1 和 2,unit_prices 可以保持不变。对于 3,四舍五入到小数点后 2 位就足够了,例如(500 / 1600).round(2)

当浮动变长时会出现问题:

# 4
unit_price = 400 / 56000 # = 0.007142857142857143

显而易见的是,浮动相当长。在这种情况下,目标是四舍五入到第一个有效数字。

我考虑过使用正则表达式来匹配第一个非零小数,或者找到第二部分的长度并应用一些逻辑:

非常欢迎任何帮助

标签: ruby-on-railsrubyalgorithmdecimal

解决方案


One should use BigDecimal for this kind of computation.

require 'bigdecimal'

bd = BigDecimal((400.0 / 56000).to_s)
#⇒ 0.7142857142857143e-2
bd.exponent
#⇒ -2

Example:

[10_000.0 / 1_000, 300.0 / 1_000, 600.0 / 800,
                   500.0 / 1_600, 400.0 / 56_000].
  map { |bd| BigDecimal(bd.to_s) }.
  map do |bd|
    additional = bd.exponent >= 0 ? 0 : bd.exponent + 1 
    bd.round(2 - additional) # THIS
  end.
  map(&:to_f)
#⇒ [10.0, 0.3, 0.75, 0.31, 0.007]

推荐阅读