Nill output message (classes)

I’m trying to practice and learn by making my first program. I just
started learning about classes so I decided to convert the whole program
so it has a class in it.
It was successful (kinda), but in the end I don’t know why but I’m
getting a nill message between the lines.
Doesn’t nill mean when an outputs value is 0?
Thank you for the help, I appreciate every suggestion!
I’m really enjoying ruby so far. :slight_smile:

require_relative ‘font_bold’

class CreditCalculator

def initialize(balance, apr, payment)
@balance = balance
@mpr = Float(apr /12)
@payment = payment
end

def calculate
$m_counter = 0
$total = @balance

while @balance > 0
  $m_counter += 1
  remaining_interest = @balance / 100 * @mpr
  $total += remaining_interest
  @balance += remaining_interest
  @balance -= @payment
  principal = @payment - remaining_interest
  interest_paid = @payment - principal

  if @balance < 0 then @balance = 0 end

  interest_paid = interest_paid.round(2)
  principal = principal.round(2)
  @balance = @balance.round(2)


  puts "#{$m_counter.to_s.ljust(7)} #{@payment.to_s.ljust(12)}

#{interest_paid.to_s.ljust(17)} #{principal.to_s.ljust(21)}
#{@balance.to_s.ljust(1)}"
puts
end

end
end

puts “Welcome to your credit card payment calculator!”.bold
puts

puts “Please tell me your credit card balance.”
balance = gets.chomp.to_f

puts “Please enter your APR!”
apr = gets.chomp.to_f

puts “How much $ would you like to pay every month?”
payment = gets.chomp.to_f

puts
puts “Month”.ljust(8).bold + “Payment”.ljust(13).bold + “Interest
Paid”.ljust(18).bold + “Principal Paid”.ljust(22).bold + “Remaining
Balance”.bold

debt = CreditCalculator.new(balance, apr, payment)
p debt.calculate

puts
puts “Monthly payment:” + “$”.rjust(3) + “#{payment}”
puts “Balance payoff: #{$m_counter.to_s.rjust(4)} months”
puts “Total payments:” + “$”.rjust(4) + $total.round(2).to_s

If you’re using IRB you’ll get “nil” as a return value when you perform
certain actions like creating a method. This is normal, it just shows
you that nothing is returned.

If you’re referring to nil outputs somewhere else, can you demonstrate?

I’m referring to the bill between the monthly results and the overall
results. That’s why I’m wondering because the method has already been
run with results and it still puts out the nil.
Could it be because I’m using the p not puts (making a method for
.to_s)?

Welcome to your credit card payment calculator!

Please tell me your credit card balance.
50
Please enter your APR!
18
How much $ would you like to pay every month?
10

Month Payment Interest Paid Principal Paid Remaining
Balance
1 10.0 0.75 9.25 40.75

2 10.0 0.61 9.39 31.36

3 10.0 0.47 9.53 21.83

4 10.0 0.33 9.67 12.16

5 10.0 0.18 9.82 2.34

6 10.0 0.04 9.96 0.0

nil

Monthly payment: $10.0
Balance payoff: 6 months
Total payments: $52.38

The last action in the method “calculate” is “puts”. This returns nil.

On Sun, Oct 27, 2013 at 1:51 PM, Joel P. [email protected]
wrote:

The last action in the method “calculate” is “puts”. This returns nil.

To elucidate: you have the line p debt.calculate, where you probably
want
simply debt.calculate. The way it is now, you’re calling the method,
which does its own printing, and then you send the method’s return value
(nil) to p, which prints the nil.

FYI for your purposes, “gets.chomp.to_f” is the same as “gets.to_f”.

On Oct 27, 2013, at 11:09 , Joel P. [email protected] wrote:

If you’re using IRB you’ll get “nil” as a return value when you perform
certain actions like creating a method. This is normal, it just shows
you that nothing is returned.

Wrong. Nil is a value just like everything else. Something was returned:
nil.

On Oct 27, 2013, at 09:19 , Greg H. [email protected] wrote:

 puts "#{$m_counter.to_s.ljust(7)} #{@payment.to_s.ljust(12)}

#{interest_paid.to_s.ljust(17)} #{principal.to_s.ljust(21)}
#{@balance.to_s.ljust(1)}"

vs:

puts “%-7d %8.2f %8.2f %8.2f %8.2f” % [$m_counter, @payment,
interest_paid, principal, @balance]

Am 27.10.2013 17:19, schrieb Greg H.:

def initialize(balance, apr, payment)
@balance = balance
@mpr = Float(apr /12)
@payment = payment
end

@balance = balance.to_f
@payment = payment.to_f

I would do conversion to float here, to make sure
nothing strange happens below…

def calculate
$m_counter = 0
$total = @balance

while @balance > 0
  $m_counter += 1
  remaining_interest = @balance / 100 * @mpr

…because here you are assuming @balance is float.

Note: 50 / 100 * 1.5 = 0.0

In fact, in your program you correctly initialize your calculator
instance with float values, but you really shouldn’t rely on that.
The calculator should work properly with integer values, or you
have a rather difficult to find bug (no error messages but possibly
wrong results).

Regards,
Marcus

BTW. Using global variables (like $m_counter) is usually frowned upon.
You should use instance variables for those, too.

Ryan D. wrote in post #1125855:

On Oct 27, 2013, at 11:09 , Joel P. [email protected] wrote:

If you’re using IRB you’ll get “nil” as a return value when you perform
certain actions like creating a method. This is normal, it just shows
you that nothing is returned.

Wrong. Nil is a value just like everything else. Something was returned:
nil.

Fair point.
In Ruby 2.1 you get a symbol back when you define a method!

Ryan D. wrote in post #1125856:

On Oct 27, 2013, at 09:19 , Greg H. [email protected] wrote:

 puts "#{$m_counter.to_s.ljust(7)} #{@payment.to_s.ljust(12)}

#{interest_paid.to_s.ljust(17)} #{principal.to_s.ljust(21)}
#{@balance.to_s.ljust(1)}"

vs:

puts “%-7d %8.2f %8.2f %8.2f %8.2f” % [$m_counter, @payment,
interest_paid, principal, @balance]

Wow… didn’t know that. :smiley:
Could you explain it how it works? :slight_smile:

Robert K. wrote in post #1125859:

On Sun, Oct 27, 2013 at 8:03 PM, Joel P. [email protected]
wrote:

FYI for your purposes, “gets.chomp.to_f” is the same as “gets.to_f”.

Even better Float(gets) returns a float and throws if the input is not
a floating point number:

That way you avoid converting invalid input to 0.0.

Kind regards

robert

Thank you! Didn’t know that neither. I’m learning a lot here. :smiley:
I don’t need the .chomp? Isn’t it so it doesn’t save the enter pressed
after it? :s

On Sun, Oct 27, 2013 at 8:03 PM, Joel P. [email protected]
wrote:

FYI for your purposes, “gets.chomp.to_f” is the same as “gets.to_f”.

Even better Float(gets) returns a float and throws if the input is not
a floating point number:

irb(main):001:0> gets.to_f
1
=> 1.0
irb(main):002:0> gets.to_f
foo
=> 0.0
irb(main):003:0> Float(gets)
1
=> 1.0
irb(main):004:0> Float(gets)
foo
ArgumentError: invalid value for Float(): “foo\n”
from (irb):4:in Float' from (irb):4 from /usr/bin/irb:12:in

That way you avoid converting invalid input to 0.0.

Kind regards

robert

On Mon, Oct 28, 2013 at 7:52 PM, Calvin Bornhofen
[email protected] wrote:

On 28.10.2013 19:36, Greg H. wrote:

Wow… didn’t know that. :smiley: Could you explain it how it works? :slight_smile:

the method at work here is #% which formats the receiver by substituting the
placeholders with the arguments it gets. You can read about all formatting
options over in the docs of Kernel#sprintf (String#% uses the same rules):
Module: Kernel (Ruby 2.0.0)

Frankly, before I write

puts “%-7d %8.2f %8.2f %8.2f %8.2f” % [$m_counter, @payment,
interest_paid, principal, @balance]

I’d write

printf “%-7d %8.2f %8.2f %8.2f %8.2f”, $m_counter, @payment,
interest_paid, principal, @balance

anytime. Much more straightforward. IMHO String#% is best used with a
single argument. As soon as you start having multiple values you need
an explicit Array as show above. But then one can also use (s)printf.

Kind regards

robert

Hello,

On 28.10.2013 19:36, Greg H. wrote:

Wow… didn’t know that. :smiley: Could you explain it how it works? :slight_smile:

the method at work here is #% which formats the receiver by substituting
the placeholders with the arguments it gets. You can read about all
formatting options over in the docs of Kernel#sprintf (String#% uses the
same rules):

Regards,
Calvin