b.herring
b.herring

Reputation: 643

How to read percentage as decimal number?

I'm trying to find the decimal value from a percentage that a user inputs.

For example, if a user inputs "15", i will need to do a calculation of 0.15 * number.

I've tried using .to_f, but it returns 15.0:

15.to_f
#=> 15.0

I also tried to add 0. to the beginning of the percentage, but it just returns 0:

15.to_s.rjust(4, "0.").to_i
#=> 0

Upvotes: 0

Views: 482

Answers (2)

Stefan
Stefan

Reputation: 114158

I'm trying to find the amount from a percentage that a user inputs

If you retrieve the input via gets, you typically convert it to a numeric value first, e.g.

percentage = gets.to_i
#=> 15

Ruby is not aware that this 15 is a percentage. And since there's no Percentage class, you have to convert it into one of the existing numeric classes.

15% is equal to the fraction 15/100, the ratio 15:100, or the decimal number 0.15.

If you want the number as a (maybe inexact) Float, you can divide it by 100 via fdiv:

15.fdiv(100)
#=> 0.15

If you prefer a Rational you can use quo: (it might also return an Integer)

15.quo(100)
#=> (3/20)

Or maybe BigDecimal for an arbitrary-precision decimal number:

require 'bigdecimal'

BigDecimal(15) / 100
#=> 0.15e0

BigDecimal also accepts strings, so you could pass the input without prior conversion:

input = gets
BigDecimal(input) / 100
#=> 0.15e0

Upvotes: 0

Todd A. Jacobs
Todd A. Jacobs

Reputation: 84343

Divide by 100.0

The easiest way to do what you're trying to do is to divide your input value by a Float (keeping in mind the inherent inaccuracy of floating point values). For example:

percentage = 15
percentage / 100.0
#=> 0.15

One benefit of this approach (among others) is that it can handle fractional percentages just as easily. Consider:

percentage = 15.6
percentage / 100.0
#=> 0.156

If floating point precision isn't sufficient for your use case, then you should consider using Rational or BigDecimal numbers instead of a Float. Your mileage will very much depend on your semantic intent and accuracy requirements.

Caveats

Make sure you have ahold of a valid Integer in the first place. While others might steer you towards String#to_i, a more robust validation is to use Kernel#Integer so that an exception will be raised if the value can't be coerced into a valid Integer. For example:

print "Enter integer: "
percentage = Integer gets

If you enter 15\n then:

percentage.class
#=> Integer

If you enter something that can't be coerced to an Integer, like foo\n, then:

ArgumentError (invalid value for Integer(): "foo\n")

Using String#to_i is much more permissive, and can return 0 when you aren't expecting it, such as when called on nil, an empty string, or alphanumeric values that don't start with an integer. It has other interesting edge cases as well, so it's not always the best option for validating input.

Upvotes: 1

Related Questions