ruby-on-rails - 如何在 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
显而易见的是,浮动相当长。在这种情况下,目标是四舍五入到第一个有效数字。
我考虑过使用正则表达式来匹配第一个非零小数,或者找到第二部分的长度并应用一些逻辑:
unit_price.match ~= /[^.0]/
unit_price.to_s.split('.').last.size
非常欢迎任何帮助
解决方案
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]
推荐阅读
- ios - M1 Air 上的 React Native 无法为 iOS 构建
- java - 需要帮助以通用模式将 JavaObject 转换为 Json
- c# - 包发布者名称
- java - 获取 ManyToMany JPA+Hibernate 的集合时出错
- php - 在 Lumen 测试期间无法使用外观
- javascript - 如何编写一个生成唯一随机数列表的有效算法?
- angular - Angular - 错误 TS2322:类型“对象”不可分配给国家列表的类型“从不 []”
- c - 为什么我的二进制到十进制转换器程序中只有前 2 个输出正确?
- android - 在 TabLayout Android 中选择/取消选择时更改标签字体大小
- java - 在android中为按钮组件设置onclick功能后,我们是否必须点击按钮2次?