Truncate a floating point number without rounding up

拟墨画扇 提交于 2019-12-21 03:28:21

问题


I have a floating point number that I want to truncate to 3 places but I don't want to round up.

For example, convert 1.0155555555555555 to 1.015 (not 1.016).

How would I go about doing this in Ruby?


回答1:


Assuming you have a float, try this:

(x * 1000).floor / 1000.0

Result:

1.015

See it working online: ideone




回答2:


You can also convert to a BigDecimal, and call truncate on it.

1.237.to_d.truncate(2).to_f # will return 1.23



回答3:


Since ruby 2.4 Float#truncate method takes as an optional argument a number of decimal digits:

1.0155555555555555.truncate(3)
# => 1.015



回答4:


Multiply by a thousand, floor, divide by a thousand, making sure to do a float division.

(x * 1000).floor / 1000.0

Or, in Ruby 1.9.2, using a version of round that wasn't available in earlier versions,

(x - 0.0005).round(3)



回答5:


sid's answer is fine but it misses the first requirement and thus fails Anwar's test. the requirement there is we must start raw so that ruby does not convert the number readily. and to start raw as raw gets is to use a plain string, so

> "59.99999999999999999999".to_d.truncate(2)
=> #BigDecimal:55a38a23cd68,'0.5999E2',18(45)>
> "59.99999999999999999999".to_d.truncate(2).to_s
=> "59.99"
> "59.99999999999999999999".to_d.truncate(2).to_f
=> 59.99

just sharing this now, since i just encountered this problem myself today : )




回答6:


This solution is based on a brilliant BigDecimal trick by @SidKrishnan, but can also handle bigger floats without faltering on precision issues.

# Truncate a floating-point value without rounding up.
#
#   trunc_float(1.999, 2)   # => 1.99
#   trunc_float(1.999, 0)   # => 1.0
#
# @param value [Float]
# @param precision [Integer]
# @return [Float]
def trunc_float(value, precision)
  BigDecimal(value.to_s).truncate(precision).to_f
end

#--------------------------------------- Test

describe ".trunc_float" do
  def call(*args)
    trunc_float(*args)
  end

  it "generally works" do
    [
      [[1, 0], 1.0],
      [[1.999, 4], 1.999],
      [[1.999, 3], 1.999],
      [[1.999, 2], 1.99],
      [[1.999, 1], 1.9],
      [[1.999, 0], 1.0],
      [[111111111.9999999, 3], 111111111.999],
      [[1508675846.650976, 6], 1508675846.650976],
    ].each do |input, expected|
      output = call(*input)
      expect([input, output]).to eq [input, expected]
    end
  end
end



回答7:


I saw the more 'computational' way of doing this is not within the answers. You can consider using the method below.

This will also work in other programming languages, like C/ Java/ Python etc. (however the casting syntax would be different).

q = 1.0155555555555555
(q * 1000).to_i / 1000.0
=> 1.015



回答8:


You can do this using regex, since ruby/rails have precision limit.

-- first convert the number to string and then do following -

input = "114.99999999999999999999"

input[/\d+.\d/]

114.99



来源:https://stackoverflow.com/questions/8106677/truncate-a-floating-point-number-without-rounding-up

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!