Ruby/Rails - Converting an integer into a float excluding existing zeros - ruby-on-rails

There must be a simple way to achieve this, I have an DB field containing an integer and I want to reformat it into a float to display.
As an integer my value looks like 6500 and I want it to display as 65.00
Within my model I have attempted to achieve this by creating the following method
def get_payment_amount_as_number
amount = self.payment_amount
return '%.02f' % self.payment_amount.to_f
end
Which results in the following being displayed: 6500.00
What would the best approach be to either strip the initial zeroes or to simply insert a decimal point?
Whilst I imagine this a ruby related question, I am not sure if rails has a handy helper already in place?
Thank you.

You could divide the number by 100:
payment_amount = 6595
'%.02f' % payment_amount.fdiv(100)
#=> "65.95"
'%.02f' % (payment_amount / 100.0)
#=> "65.95"
Or you could convert the number to a string and insert a decimal point:
payment_amount.to_s.rjust(3, '0').insert(-3, '.')
#=> "65.95"
Rails also provides several helpers to format numbers:
number_to_currency(65.95)
#=> "$65.95"
number_to_currency(1000)
#=> "$1,000.00"
And you might want to take a look at the money-rails gem which provides a mapping from cents to money objects.

You do this simply ...
def get_payment_amount_as_number
amount = self.payment_amount / 100
#to convert amount to float
amount.to_f
end
I find another one
amount = self.payment_amount
# => 6500
ans = '%.2f' % (amount/100)
# => "65.00"

int_value = 6500
float_value = float_value = '%.2f' % (int_value / 100.0)
puts int_value: int_value, float_value: float_value
it's all!

Related

How do I control the decimals in my float calculations?

I'm trying to run a few calculations in order to represent a particular price (ie 20.30).
I have tried the Float#round method, but the instance variables holding these values eventually start representing numbers that look like 24.43418 after a few calculations.
This is just a method I created to turn a users input into a percentage
class Fixnum
def percentage
self.to_f / 100
end
end
The #bankroll_amount and #risk_amount values should be evaluating to two decimal points
class Client
def initialize(bankroll, unit)
#bankroll_amount = bankroll.to_i.round(2)
#unit_percentage = unit.to_i.percentage
default_risk_amount.round(2)
evaluate_default_unit!.round(2)
end
def default_risk_amount
#risk_amount = #unit_percentage * #bankroll_amount
#risk_amount.round(2)
end
# simulates what an updated bankroll looks like after a win based on clients "unit" amount
def risk_win
#bankroll_amount = #bankroll_amount + #risk_amount
#bankroll_amount.round(2)
evaluate_default_unit!.round(2)
end
# simulates what a clients updated bankroll looks like after a loss based on clients "unit" amount
def risk_loss
#bankroll_amount = #bankroll_amount - #risk_amount
evaluate_default_unit!
end
def evaluate_default_unit!
#risk_amount = #unit_percentage * #bankroll_amount.round(2)
end
end
Im not sure if this has anything to do with the fact that I am initializing these instance variables or not, but the #risk_amount returns the correct two decimal value, but when I return the object, the instance variable inside has running decimals.
c = Client.new 2000, 1
<Client:0x000001018956a0 #bankroll_amount=2000.0, #unit_percentage=0.01, #risk_amount=20.0>
c.risk_win
=> 20.2
When I run c.risk_win enough, it eventually returns
c
<Client:0x000001018956a0 #bankroll_amount=2440.3802, #unit_percentage=0.01, #risk_amount=24.4038>
This is one way to show only two decimal points.
price = 20.21340404
"%.2f" % price
# => 20.23
Also see RAILS number_to_currency helpers ActionView::Helpers::NumberHelper
http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html#method-i-number_to_currency
Use number_with_precision to format the display of your floating point numbers to 2 decimal places:
number_with_precision(#bankroll_amount.to_f, precision: 2)
Usage in rails console:
[1] pry(main)> include ActionView::Helpers::NumberHelper
=> Object
[2] pry(main)> number_with_precision(2440.3802, precision: 2)
=> "2440.38"

to_d to always return 2 decimals places in ruby

I'm dealing with currencies and I want to round down the number to 2 decimal places. Even if the number is 500.0, I would like it to be 500.00 to be consistent. When I do "500.00".to_d it converts it to 500.0.
Whats a good way of changing this behavior? I also use this method to round down to 2 digits and make sure it always has 2 decimals.
def self.round_down(x, n=2)
s = x.to_s
l = s.index('.') ? s.index('.') + 1 + n : s.length
s = s[0, l]
s = s.index('.') ? s.length - (s.index('.') + 1) == 1 ? s << '0' : s : s << '.00'
s.to_f
end
In addition to mcfinnigan's answer, you can also use the following to get 2 decimal places
'%.2f' % 500 # "500.00"
This use case is known as the string format operator
Since you are using Rails and this seems to be related to a view, there's number_with_precision:
number_with_precision(500, precision: 2)
#=> "500.00"
I18n.locale = :de
number_with_precision(500, precision: 2)
#=> "500,00"
For currencies I'd suggest number_to_currency:
number_to_currency(500)
#=> "$500.00"
Here's a hint. 500.00 is a representation of the number 500.0
Specifically, sprintf will help you:
irb(main):004:0> sprintf "%.2f", 500.0
=> "500.00"
Do not use floating point numbers to represent money. See this question for a good overview of why this is a bad idea.
Instead, store monetary values as integers (representing cents), or have a look at the money gem that provides lots of useful functionality for dealing with such values.
There was a requirement to round DOWN.
Most other answers round 500.016 UP to 500.02
Try:
def self.round_down(x, n = 2)
"%.#{n}f" % x.to_d.truncate(n)
end
irb(main):024:0> x=500.0; '%.2f' % x.to_d.truncate(2)
=> "500.00"
irb(main):025:0> x=500.016; '%.2f' % x.to_d.truncate(2)
=> "500.01"

Formatting a float to a minimum number of decimal places

I'm storing a decimal in rails and I need to have it display as a currency as such:
11.1230 => "$11.123"
11.1000 => "$11.10"
11.0100 => "$11.01"
11.1234 => "$11.1234"
Any easy way to do this?
def pad_number( number, min_decimals=2 )
s = "%g" % number
decimals = (s[/\.(\d+)/,1] || "").length
s << "." if decimals == 0
s << "0"*[0,min_decimals-decimals].max
end
puts [ 11.123, 11.1, 11.01, 11.1234, 11 ].map{ |n| pad_number(n) }
#=> 11.123
#=> 11.10
#=> 11.01
#=> 11.1234
#=> 11.00
Edit: Looks like this is Rails 3 specific, as Rails 2's number_with_precision method doesn't include the strip_insignificant_zeros option:
You can pass some options to number_to_currency (a standard Rails helper):
number_to_currency(11.1230, :precision => 10, :strip_insignificant_zeros => true)
# => "$11.123"
You need to provide a precision in order for the strip_insignificant_zeros option to work, though, otherwise the underlying number_with_precision method never gets called.
If you want to store as a float, you can use the number_to_currency(value) method in yours views for printing something that looks like $.
Correct me if I'm wrong (as I've rarely dealt with currency) but I think the conventional wisdom is to store dollar values as integers. That way you won't have to deal with funky float math.
So, convert it to three decimal fraction digits and then remove the final one if and only if it's a zero.
s.sub(/0$/, '')

How to get a variable to have 2 decimals

I have a variable i would like to force to have 2 and always 2 decimals. Im comparing to a currency. Often i get a comparison looking like the following.
if self.price != price
#do something
end
Where self.price = 120.00 and price = 120.0. The self.price is set with a :precision => 2 in the model, but how do i do the same with a variable, cause this seems to fail in comparison
Use integers for storing currency, for example, use store 100 cents for 1 dollar. It reduces headaches and may improve performance if it matters.
class Numeric
def round_to( decimals=0 )
factor = 10.0**decimals
(self*factor).round / factor
end
end
if self.price.round_to(2) != price.round_to(2)
#do something
end

Converting filesize string to kilobyte equivalent in Rails

My objective is to convert form input, like "100 megabytes" or "1 gigabyte", and converts it to a filesize in kilobytes I can store in the database. Currently, I have this:
def quota_convert
#regex = /([0-9]+) (.*)s/
#sizes = %w{kilobyte megabyte gigabyte}
m = self.quota.match(#regex)
if #sizes.include? m[2]
eval("self.quota = #{m[1]}.#{m[2]}")
end
end
This works, but only if the input is a multiple ("gigabytes", but not "gigabyte") and seems insanely unsafe due to the use of eval. So, functional, but I won't sleep well tonight.
Any guidance?
EDIT: ------
All right. For some reason, the regex with (.*?) isn't working correctly on my setup, but I've worked around it with Rails stuff. Also, I've realized that bytes would work better for me.
def quota_convert
#regex = /^([0-9]+\.?[0-9]*?) (.*)/
#sizes = { 'kilobyte' => 1024, 'megabyte' => 1048576, 'gigabyte' => 1073741824}
m = self.quota.match(#regex)
if #sizes.include? m[2].singularize
self.quota = m[1].to_f*#sizes[m[2].singularize]
end
end
This catches "1 megabyte", "1.5 megabytes", and most other things (I hope). It then makes it the singular version regardless. Then it does the multiplication and spits out magic answers.
Is this legit?
EDIT AGAIN: See answer below. Much cleaner than my nonsense.
You can use Rails ActiveHelper number_to_human_size.
def quota_convert
#regex = /([0-9]+) (.*)s?/
#sizes = "kilobytes megabytes gigabytes"
m = self.quota.match(#regex)
if #sizes.include? m[2]
m[1].to_f.send(m[2])
end
end
Added ? for optional plural in the regex.
Changed #sizes to a string of plurals.
Convert m[1] (the number to a float).
Send the message m[2] directly
why don't you simply create a hash that contains various spellings of the multiplier as the key and the numerical value as the value? No eval necessary and no regexs either!
First of all, changing your regex to #regex = /([0-9]+) (.*?)s?/ will fix the plural issue. The ? says match either 0 or 1 characters for the 's' and it causes .* to match in a non-greedy manner (as few characters as possible).
As for the size, you could have a hash like this:
#hash = { 'kilobyte' => 1, 'megabyte' => 1024, 'gigabyte' => 1024*1024}
and then your calculation is just self.quota = m[1].to_i*#hash[m2]
EDIT: Changed values to base 2

Resources