Ruby: What is the difference between these two blocks of code? - ruby

Below, I will provide 2 different blocks of code:
Code Block A, while I know there are better ways of writing it, it's where my thought process was initially going
Code Block B is a much more concise way of the aforementioned code
Code Block A:
print "How much was your meal?"
meal_cost = Float(gets)
meal_cost = '%.2f' % meal_cost
print "What is the tax percentage in your state?"
tax_percent = Float(gets)
tax_percent = '%.2f' % tax_percent
tax_value = meal_cost.to_f * (tax_percent.to_f * 0.01)
tax_value = '%.2f' % tax_value
meal_with_tax = tax_value.to_i + meal_cost.to_i
meal_with_tax = '%.2f' % meal_with_tax
print "What percentage would you like to tip?"
tip_percent = Float(gets)
tip_value = (tip_percent.to_i * 0.01) * meal_with_tax.to_i
tip_value = '%.2f' % tip_value
total_cost = tip_value.to_i + meal_with_tax.to_i
total_cost = '%.2f' % total_cost
puts "The pre-tax cost of your meal was $#{meal_cost}."
puts "At #{tax_percent}%, tax for this meal is $#{tax_value}."
puts "For a #{tip_percent}% tip, you should leave $#{tip_value}."
puts "The grand total for this meal is then $#{total_cost}"
Code Block B:
puts "How much was your meal?"
meal_cost = Float(gets)
puts "Please enter your tax rate as a percentage (e.g., 12, 8.5)"
tax_percent = Float(gets)
puts "What percentage of your bill would you like to tip? (e.g., 15)"
tip_percent = Float(gets)
tax_value = meal_cost * tax_percent/100
meal_with_tax = meal_cost + tax_value
tip_value = meal_with_tax * tip_percent/100
total_cost = meal_with_tax + tip_value
print "The pre-tax cost of your meal was $%.2f.\n" % meal_cost
print "At %d%%, tax for this meal is $%.2f.\n" % [tax_percent, tax_value]
print "For a %d%% tip, you should leave $%.2f.\n" % [tip_percent, tip_value]
print "The grand total for this meal is then $%.2f.\n" % total_cost
For some reason, in Code Block A, the following lines:
meal_with_tax = tax_value.to_i + meal_cost.to_i
meal_with_tax = '%.2f' % meal_with_tax
returns 22 instead of 22.4
Can someone help me understand why?

to_i returns an integer.
you may want to use to_f to maintain precision
or value.round(1) may be the solution you're looking for

When you are converting tax_value and meal_cost to integers with .to_i in code block a you are losing precision.

to_i stands for 'to integer'. An integer is a number without a decimal point, so anything after the deciaml point will get thrown away after you call to_i.
x = 22.123456
y = 22.999999
x == y #=> false
x.to_i == y.to_i #=> true

Related

My ruby calculator won't output to my console

So I'm using atom to code up a calculator and I can't seem to get the console to output the first instance of puts. It just says [Finished in 2.88s]. Is there anything missing that's causing my code to not be printed to the console or am I just stupid to think that it should be outputting anything to the console? Here is my code:
def add
puts "What is the first number to be added?"
n1 = gets.chomp
puts "What is the second number to be added?"
n2 = gets.chomp
answer = n1 + n2
puts "Congrats, your number is #{answer}"
end
def sub
puts "What is the first number to be subtracted?"
n1 = gets.chomp
puts "What is the second number to be subtracted?"
n2 = gets.chomp
answer = n1 - n2
puts "Congrats, your number is #{answer}"
end
def multiply
puts "What is the first number to be multiplied?"
n1 = gets.chomp
puts "What is the second number to be multiplied?"
n2 = gets.chomp
answer = n1 * n2
puts "Congrats, your number is #{answer}"
end
def divide
puts "What is the first number to be divided?"
n1 = gets.chomp
puts "What is the second number to be divided?"
n2 = gets.chomp
answer = n1 / n2
puts "Congrats, your number is #{answer}"
end
print "Would you like to add, subtract, multiply, or divide a number? "
response = gets.chomp
if response == "add" then
add
elsif response == "subtract" then
sub
elsif response == "multiply" then
multiply
else response == "divide"
divide
end

Ruby: Am I using the correct scope?

I come from a JavaScript background and wrote this similar to how I would in javascript. I am writing it in Ruby.
This is a codewars exercise.
n being 0 and 1 returns 0.00 and 1.00 as expected. Every other positive natural number returns 0.
# Task:
# Your task is to write a function which returns the sum of following series upto nth term(parameter).
# Series: 1 + 1/4 + 1/7 + 1/10 + 1/13 + 1/16 +...
# Rules:
# You need to round the answer to 2 decimal places and return it as String.
# If the given value is 0 then it should return 0.00
# You will only be given Natural Numbers as arguments.
# Examples:
# SeriesSum(1) => 1 = "1.00"
# SeriesSum(2) => 1 + 1/4 = "1.25"
# SeriesSum(5) => 1 + 1/4 + 1/7 + 1/10 + 1/13 = "1.57"
def series_sum(n)
sum = 0
if n == 0
return 0.00
elsif n == 1
return 1.00
else
n.times do |i|
if i == 1
sum += 1
break
end
sum += 1/( 1 + (3 * (i - 1)) )
end
end
return sum
end
puts series_sum(0)
puts series_sum(1)
puts series_sum(2)
puts series_sum(4)
puts series_sum(5)
A couple of things to note:
- Ruby has reduce method that can sum up a list of numbers: https://apidock.com/ruby/Enumerable/reduce
- You don't need to explicitly return from your method. Ruby automatically returns the last statement in your method.
I've modified your solution, and this should work:
def series_sum(n)
if n > 1
sum = (1..n).inject { |sum, i| sum + (1/(1.to_f + (3 * (i - 1)))) }
else
sum = n
end
'%.2f' % sum
end
When you are expecting a decimal number in a division, always make sure that either the numerator or the denominator is in float, hence the reason for the 1.to_f.
'%.2f' is a string format to ensure the final answer is returned in 2 decimal places.
There are two parts to this question.
How to display an operation's result as a float value?
1/2 # this will give 0
1.0/2 # this will give 0.5
How to limit a float value to 2 decimal places?
You can use the round function
22.0/7 # this will give pi value - 3.142857142857143
(22.0/7).round(2) # this will give 3.14
The two answers above can be combined to get your answer. I would leave it as an exercise for you to come up with the exact code to solve your problem.
def series_sum(n)
return "0.00" if n.zero?
sprintf("%.2f", (0..n-1).sum { |m| 1.fdiv(3*m+1) }.round(2))
end
series_sum(0) #=> "0.00"
series_sum(1) #=> "1.00"
series_sum(2) #=> "1.25"
series_sum(3) #=> "1.39"
series_sum(4) #=> "1.49"
series_sum(5) #=> "1.57"
See Kernel#sprintf. One could alternatively use String%, which shares sprintf's formatting directives:
"%.2f" % (0..n-1).sum { |m| 1.fdiv(3*m+1) }.round(2)
I am not aware of the existence of a closed-form expression for this partial sum. Though not relevant to the question, this partial sum can be shown to be divergent.

Insert chosen number within range, squared and cubed

I am trying to set a range for allowed user inputted numbers. Then, I want to print that chosen number squared and cubed.
I tried the following:
class Range
def clamp(min, max)
self < min ? min : self > max ? max : self
end
end
class Multiply
def initialize(id, squared, cubed)
#id = num
#squared = (num * num)
#cubed = (num * num * num)
end
end
# #limit = (params[:limit] || 10).clamp(0, 100)
puts 'Please insert your favorite number between 1 and 100.'
num = gets.to_i
puts 'You picked ' + num.to_s + '?'
puts 'You picked ' + num.to_s.Multiply.squared + '?'
The #limit throws 'params' not found.
How can I run num through classes Range and Multiply before it puts?
I am trying to set a range for 'allowed' user inputted numbers, then I
want to print that chosen number squared, and cubed.
Use the clamp method available to Numeric via the Comparable module:
input = '110'
clamped = input.to_i.clamp(0,100)
puts clamped
#100
You can attain powers of numbers with Integer#** or Float#**. If one must produce DIY methods by extending core classes, then you can for example extend the Numeric class by defining the methods clamp, square and cube there. square could be:
class Numeric
def square
self ** 2
end
end
10.square #=> 100

Trying to figure out if user input is prime or not with ruby

I am new to Ruby and just read about methods and such I have been working on a program in order to get the user to type in a number and determine if it is prime or not. This is what I have so far.
print "Enter a number: "
num = gets.chomp
def prime(n)
factors = []
if num < 2
puts "#{num} is a prime number"
end
while n % num == 0 and num < n
factors.push(num)
num += 1
end
return factors
end
Not even sure if I'm on the right track. Really lost. Any help would be greatly appreciated!
require 'prime'
print "Enter a number: "
num = gets.chomp
Prime.prime?(n)
Or, from the scratch:
def prime?(n)
if n > 1
min_condition = Math.sqrt(n).to_i # The highest factor is necessary at most sqrt(n)
factors = 0
(1..min_condition).step(2).each do |i| # It's not necessary to check even numbers
factors += 1 if (n.to_f / i) % 1 == 0
break if factors > 1 # If the algorithm find 2 factors, the number isn't prime
end
!(factors > 1)
else
false
end
end
I know that you're doing this to learn Ruby, but keep in mind that you can just use Prime.prime? to determine whether or not a number is prime.
require 'prime'
Prime.prime?(3)
#=> true
Prime.prime?(4)
#=> false
As for your actual problem, you use both num and n inside your method, but num is defined outside, so won't be in scope. Also: you never seem to actually be calling prime.
There are some problems with your program:
You want to get the user to type in a number and determine if it is
prime or not but the output of your method prime doesn't answer
this question. It will return an array.
If a number is less then 2, it is not a prime number (wikipedia), so this piece of your code is wrong:
if num < 2
puts "#{num} is a prime number"
end
There are plenty of ways to check if a number is a prime number or not, this topic may help you to implement with Ruby.
If you don't want to use ruby base library than below code is useful for you
print "Enter a number: "
num = gets.chomp
def check_prime_number(num)
num = num.to_i
n = 1
factors = []
while (num >= n ) do
if (num % n == 0 )
factors << n unless factors.include?(n)
end
n += 1
end
if ( factors.size > 2)
puts "Factors of number #{num} :-> #{factors}"
elsif num > 0
puts "#{num} is prime"
end
end
check_prime_number(num)
Try if its helpful for you.

How do I write a math formula?

I need to write the following formula in code:
C ((i/100)(n/365)+1)
This means that i should be divided by 100, n should be divided by 365, both results must be multiplied, the resulting number should be added 1 and the resulting number should be multiplied by C.
I was able to write the following code, but there is an error in the math operation I cannot fix:
puts "Insert money to invest:"
money_invested = gets.to_i
puts "Indicate in days the period of deposit:"
time_investment = gets.to_i
puts "Indicate interest rate:"
interest_rate = gets.to_i
investment_calculation = money_invested * (([interest_rate / 100] [time_investment / 365]) + 1)
puts "Your refund will be $#{investment_calculation.round(2)}."
try this:
investment_calculation = money_invested * (((interest_rate / 100) * (time_investment / 365) + 1))
1) you used [] instead of ().
in ruby [] corresponds to a list
2) you need to use * to multiply the results of (interest_rate / 100) and (time_investment / 365)
EDIT
If you are using decimals your code wouldn't work, you would need to use to_f instead of to_i
like this: interest_rate = gets.to_f
When you divide two integers in Ruby, you get integer division (the result is an integer):
irb(main):001:0> 1343/1000
#=> 1
If you want a floating point number, then you need at least one of the two numbers to be a floating point value:
irb(main):002:0> 1343/1000.0
#=> 1.343
irb(main):003:0> 1343.0/1000
#=> 1.343
You can do this by making the user input into floating point numbers instead of integers (use to_f instead of to_i), or by using floating point constants in your formula. The first will suffice, and makes sense, in case the user types in 50.75 for their money. ("50.75".to_i #=> 50)
puts "Insert money to invest:"
money_invested = gets.to_f
puts "Indicate in days the period of deposit:"
time_investment = gets.to_f
puts "Indicate interest rate:"
interest_rate = gets.to_f
investment_calculation = money_invested * (1 + interest_rate/100 * time_investment/365)
puts "Your refund will be $%.2f." % investment_calculation
Note that I've used String#% method with %.2f to format your number to two decimals. This is because 3.round(2) yields the number 3.0 and not the string "3.00" as you desire.

Resources