Truncate a floating point number without rounding up

℡╲_俬逩灬. 提交于 2019-12-03 09:43:26

Assuming you have a float, try this:

(x * 1000).floor / 1000.0

Result:

1.015

See it working online: ideone

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

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

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

1.0155555555555555.truncate(3)
# => 1.015

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)

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 : )

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

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

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

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