So I'm trying some code out to convert numbers into strings. However, I noticed that in certain cases it does not preserve the last two decimal places. For instance I type 1.01 and 1.04 for addition and I get back 2.04. If I type just 1.05 it preserves the number and returns it exactly. I get whats going on things are being rounded. I don't know how to prevent it from being rounded though. Should I just consider sending (1.01+1.04) to self as only one input?
Warning! I haven't tried this yet so don't know if its supported:
user_input = (1.04+1.01) #entry from user
user_input = gets.to_f
user_input.to_test_string
What I have so far:
class Float
def to_test_string
cents = self % 1
dollars = self - cents
cents = cents * 100
text = "#{dollars.to_i.en.numwords} dollars and #{cents.to_i.en.numwords} cents"
puts text
text
end
end
puts "Enter two great floating point numbers for adding"
puts "First number"
c = gets.to_f
puts "Second number"
d = gets.to_f
e = c+d
puts e.to_test_string
puts "Enter a great floating number! Example 10.34"
a = gets.to_f
puts a.to_test_string
Thanks for the help! Post some code up so I can try!
First of all: never use float for money — Use Float or Decimal for Accounting Application Dollar Amount?
irb> x = 1.01 + 1.04
=> 2.05
irb> y = x % 1
=> 0.04999999999999982
irb> (y * 100).to_i
=> 4
But if want it VERYVERYVERY much:
irb> (y * 100).round.to_i
=> 5
$ python
Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41)
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 1.04+1.01
2.0499999999999998
Read this: What Every Computer Scientist Should Know About Floating-Point Arithmetic
Also, what Nakilon said.
This is not a problem with ruby, nor your code (although you need to get rid of .en.numwords); it is a problem with the binary floating point representation.
You should use a Fixnum or Bignum to represent the currency.
eg.
class Currency
def initialize str
unless str =~ /([0-9]+)\.([0-9]{2})/
raise 'invalid currency string'
end
#cents = $1.to_i * 100 + $2.to_i
end
end
Related
I wrote the following code in Ruby for Celsius to Fahrenheit conversion. I keep getting error. I am sure that I am still not clear on the concept of methods and that's why I cant figure it out.
puts "Enter the Degree in c:"
c = gets.chomp
def celsius_fahrenheit (f)
return f = ( c * 9 / 5) + 32
end
answer = "The #{celsius_fahrenheit (f)} equivalent is"
puts answer
You have several problems:
convert c to Float
change signature of celsius_fahrenheit to use c as a parameter
don't do an assignment in the method's body
Here is the code:
def celsius_fahrenheit(c)
c * 9 / 5 + 32
end
puts 'Enter C:'
c = gets.to_f
puts celsius_fahrenheit(c)
How do I convert a string with a dollar amount such as "5.32" or "100" to an integer amount in cents such as 532 or 10000?
I have a solution below:
dollar_amount_string = "5.32"
dollar_amount_bigdecimal = BigDecimal.new(dollar_amount_string)
cents_amount_bigdecimal = dollar_amount_bigdecimal * BigDecimal.new(100)
cents_amount_int = cents_amount_bigdecimal.to_i
but it seems wonky. I want to be sure because this will be an input to the PayPal API.
I've also tried the money gem, but it wasn't able to take strings as inputs.
You can use String#to_r ("to rational") to avoid round-off error.
def dollars_to_cents(dollars)
(100 * dollars.to_r).to_i
end
dollars_to_cents("12")
#=> 1200
dollars_to_cents("10.25")
#=> 1025
dollars_to_cents("-10.25")
#=> -1025
dollars_to_cents("-0")
#=> 0
d, c = dollar_amount_string.split(".")
d.to_i * 100 + c.to_i # => 532
I started with the original accepted answer, but had to make some important fixes along the way:
def dollars_to_cents(string=nil)
# remove all the signs and formatting
nums = string.to_s.strip.delete("$ CAD ,")
# add CENTS if they do not exit
nums = nums + ".00" unless nums.include?(".")
return (100 * nums.strip.to_r).to_i
end
So far works with these inputs:
CAD 1,215.92
CAD 1230.00
$11123.23
$123
43234.87
43,234.87
I'm making a interest calculator
I go 10 * .10 * 10 and i get 0 so how do i multiply a decimal without it being 0?
my source code is
def interest()
puts "Type the original loan."
loan = gets.chomp.to_i
puts "Type the amount of interest in decimal."
interest = gets.chomp.to_i
puts "How many years?"
years = gets.chomp.to_i
puts "Your interest is"
puts loan * interest * years
end
interest()
You've got integers there, so result will be an integer too. You could use 'to_f but beware, it's not good for dealing with money or anything else needing precision. Use BigDecimal instead:
require 'bigdecimal'
def interest
puts "Type the original loan."
loan = BigDecimal(gets.chomp)
puts "Type the amount of interest in decimal."
interest = BigDecimal(gets.chomp)
puts "How many years?"
years = BigDecimal(gets.chomp) # suggested in comment, agreed with that
puts "Your interest is"
puts loan * interest * years
end
What's the difference between them?
Do this
interest = gets.chomp.to_f
.to_i changes the string to an integer. An integer is a WHOLE number.
.to_f is to float, a float is a number that allows decimal places
The problem is that you're using .to_i when you don't really want to use integers here. Integers are represented without decimal parts to them, and therefore when you call .10.to_i it truncates it to 0.
Consider using floats by .to_f instead
So I'm writing what I thought was a simple .rb file to convert a float number into a string. The string returns my floating point number in words. So if I have 11.11 then I would have eleven dollars and eleven cents So far I've extended the float class which has worked alright. I'm having trouble with how to convert the 11 cents into eleven cents. en.numwords would kick back eleven point one one. I've thought about trying out a hash to solve my problem where 11=>eleven cents. Any thoughts how I could implement this? Perhaps a better way to implement this?
Here's what I have so far:
require 'rubygems'
require 'linguistics'
Linguistics::use( :en )
class Float
def to_test_string
puts self #check
puts self.en.numwords
self.en.numwords
end
end
puts "Enter two great floating point numbers for adding"
puts "First number"
c = gets.to_f
puts "Second number"
d = gets.to_f
e = c+d
# puts e
puts e.to_test_string
puts "Enter a great floating number! Example 10.34"
a = gets.to_f
# puts a
puts a.to_test_string
Thanks for the help! Post some code so I can try ideas out!
Here's one solution: divide the number into two substrings based on the decimal point delimiter, call en.numwords on each substring separately, and then join the resulting strings with "point" between them. Something along the lines of:
require "rubygems"
require "linguistics"
Linguistics::use(:en)
class Float
def my_numwords
self.to_s.split('.').collect { |n| n.en.numwords }.join(' point ')
end
end
(11.11).my_numwords # => eleven point eleven
This problem can be solved by splitting the float into two values: dollars and cents.
require 'rubygems'
require 'linguistics'
Linguistics::use( :en )
class Float
def to_test_string
puts self #check
#Split into dollars and cents
cents = self % 1
dollars = self - cents
cents = cents * 100
text = "#{dollars.to_i.en.numwords} dollars and #{cents.to_i.en.numwords} cents"
puts text
text
end
end
puts "Enter two great floating point numbers for adding"
puts "First number"
c = gets.to_f
puts "Second number"
d = gets.to_f
e = c+d
# puts e
puts e.to_test_string
puts "Enter a great floating number! Example 10.34"
a = gets.to_f
# puts a
puts a.to_test_string
I have a string "1/16" I want to convert it to float and multiply it by 45. However, I dont get the desired results.
I am trying in script/console
>> "1/16".to_f
=> 1.0
>> "1/16".to_f*45
=> 45.0
how can i get the desired result of 2.81
Bigger picture:
I have a drop down like this:
<%=select_tag :volume, options_for_select(["", "1 g", "1/16 oz", "1/8 oz","1/4 oz",
"1/2 oz", "1 oz", "1/8 lb", "1/4 lb", "Single", "Multi 5" ], "N/A") %>
whenever user selects oz value then i want to multiply it to 45
so i do:
first, *rest = params[:volume].to_s.split(/ /)
if rest.first=="oz"
#indprodprice = #prods.orig_price.to_i*first.to_f*28.3495
else
#indprodprice = #prods.orig_price.to_i*first.to_f*453.59237
end
Use Rational
>> (Rational(*("1/16".split('/').map( &:to_i )))*45).to_f
=> 2.8125
Looks like you're going to have to parse the fraction yourself. This will work on fractions and whole numbers, but not mixed numbers (ie: 1½ will not work.)
class String
def to_frac
numerator, denominator = split('/').map(&:to_f)
denominator ||= 1
numerator/denominator
end
end
"1/16".to_frac * 45
#Farrel was right, and since Ruby 1.9 includes Rational and String has a to_r-method things are easier:
puts ("1/16".to_r * 45).to_f #=> 2.8125
puts ("1/16".to_r * 45).to_f.round(2) #=> 2.81
In 2.0 it became even easier with a rational literal:
1/16r # => (1/16)