新手问题 ruby round down 三位小数

VincentJiang · 2014年01月19日 · 最后由 zhang_soledad 回复于 2014年12月03日 · 9232 次阅读

如题,请问如何在 ruby 中保留三位小数,但不四舍五入? 例如1.2345保留三位小数为:1.234 谢谢!

# File activesupport/lib/active_support/core_ext/float/rounding.rb, line 11
class Float
  alias precisionless_round round
  private :precisionless_round

  # Rounds the float with the specified precision.
  #
  #   x = 1.337
  #   x.round    # => 1
  #   x.round(1) # => 1.3
  #   x.round(2) # => 1.34
  def round(precision = nil)
    if precision
      magnitude = 10.0 ** precision
      (self * magnitude).round / magnitude
    else
      precisionless_round
    end
  end
end

p 1.234567.round(4)
'%.3f' % 1.2345

sprintf '%.3f', 1.2345
(1.2345 * 1000).to_i / 1000.0

需要考虑负数的时候啊。。。

require 'bigdecimal'
require 'bigdecimal/util'

puts BigDecimal.new("1.2344").truncate(3).to_digits
puts BigDecimal.new("1.2345").truncate(3).to_digits
puts BigDecimal.new("1.2346").truncate(3).to_digits

puts BigDecimal.new("-1.2344").truncate(3).to_digits
puts BigDecimal.new("-1.2345").truncate(3).to_digits
puts BigDecimal.new("-1.2346").truncate(3).to_digits
1.234
1.234
1.234
-1.234
-1.234
-1.234
class Float
  def truncate1(n)
    (self * 10**n).truncate.to_f/10**n
  end
end

p 1.2345.truncate1(3)
7 楼 已删除

函数被覆盖了,这样肯定得报错

class Float
  alias_method :old_truncate, :truncate
  def truncate(n)
    (self * 10**n).old_truncate.to_f/10**n
  end
end

#3 楼 @zhufenggood 还是不行的

(sprintf '%.3f', 1.2346).to_f
 => 1.235

最后 我是用的笨办法

"#{1.2346}"[0..3].to_f

#9 楼 @jhjguxin 的确好笨的方法啊,ruby 有 round 方法,却没有 rounddown 的方法,真不解。。。

#8 楼 @hhuai

明白啦~ 谢谢光哥~

下面是我的想法,觉得 OK:

class Test
    def round_down(x, n)
        index_n = x.to_s.index('.') + n + 1
        puts x.to_s[0, index_n].to_f
    end
end

t = Test.new
t.round_down(1.23456, 4)

=> 1.2345

'%.3f' % ((1.2 * 1000).to_i * 0.001) => "1.200"

'%.3f' % ((1.2346 * 1000).to_i * 0.001) => "1.234"

'%.3f' % ((-1.2346 * 1000).to_i * 0.001) => "-1.234" 可以自己写个方法,支持自定义位数。

#13 楼 @zfjoy520 我试了一下,如果小数位多的话,会这样: (1.234567 * 10000).to_i * 0.0001 = 1.2345000000000002

#14 楼 @jxs471494539 后面那个你不用管他,float 本身就是不精准的, 如果你要的是字符串的话

前面加上 '%.3f' %即可。

tail = 3 # 保留小数位 num = 1.2346 # 输入数据 "%.#{tail}f" % (0.1 ** tail * (10 ** tail * num).to_i)

如果你要的是 float 的话,类似于 1.2 这种。小数位不足的,似乎是很难达到需求。

#16 楼 @zfjoy520 我比较喜欢这样的: num.to_s[0, num.to_s.index('.') + tail + 1].to_f 先转换成字符,再截取,最后转成 float,很形象的过程吧。

#17 楼 @jxs471494539

另外,还需要判断一下,如果 num 不是小数的情况,num.to_s.index('.') 会是 nil,会报错哈。

除非你非常确定 num,必是小数

num = num.to_f.to_s num[0, num.index('.') + tail + 1].to_f

这样看起来舒服些。免得两个 to_s,呵呵

#19 楼 @zfjoy520 有道理,有可能不是小数的。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号