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?
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?
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
59.99999999999999999999.to_d.truncate(2).to_f
, returns 60.0
!! –
Lewak 59.99999999999999999999.inspect
is "60.0". So the conversion happens prior to to_d
. –
Unfleshly 111111111.9999999.to_d.truncate(2).to_f
is 111111112.0
. See my hacked version below. Cheers! –
Unfleshly Assuming you have a float
, try this:
(x * 1000).floor / 1000.0
Result:
1.015
See it working online: ideone
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 have few options - some of them are mentioned in the answers above, but not all.
You can use .floor(n)
# Returns the largest number less than or equal to
# float with a precision of n digits decimal digits (default: 0).
# -> basically its rounding down the number
> 1.0155555555555555.floor(3)
1.015
You can use .truncate(n)
# Returns float truncated to a precision
# of n digits decimal digits (default: 0).
> 1.0155555555555555.truncate(3)
=> 1.015
You can use .round(n, :truncate)
(Only on BigDecimal
not on float
)
> 1.0155555555555555.to_d.round(3, :truncate).to_f
=> 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
© 2022 - 2024 — McMap. All rights reserved.