Chris Pine "Learning Programming" Question

I'm still going through Chris Pine's book on Ruby programming and came
across the following exercise. To put it simply, I just don't
understand how this code works.

def englishNumber number
  # We only want numbers from 0-100.
  if number < 0
    return 'Please enter a number zero or greater.'
  end
  if number > 100
    return 'Please enter a number 100 or lesser.'
  end

  numString = '' # This is the string we will return.

  # "left" is how much of the number we still have left to write out.
  # "write" is the part we are writing out right now.
  # write and left... get it? :slight_smile:
  left = number
  write = left/100 # How many hundreds left to write out?
  left = left - write*100 # Subtract off those hundreds.

  if write > 0
    return 'one hundred'
  end

QUESTION 1: For example, if I choose 99 as my number, left = number, and
write = left/100, wouldn't write = 99/100? In that case, why would
write > 0 return 'one hundred'?

write = left/10 # How many tens left to write out?
  left = left - write*10 # Subtract off those tens.

  if write > 0
    if write == 1 # Uh-oh...
      # Since we can't write "tenty-two" instead of "twelve",
      # we have to make a special exception for these.
      if left == 0
        numString = numString + 'ten'
      elsif left == 1
        numString = numString + 'eleven'
      elsif left == 2
        numString = numString + 'twelve'
      elsif left == 3
        numString = numString + 'thirteen'
      elsif left == 4
        numString = numString + 'fourteen'
      elsif left == 5
        numString = numString + 'fifteen'
      elsif left == 6
        numString = numString + 'sixteen'
      elsif left == 7
        numString = numString + 'seventeen'
      elsif left == 8
        numString = numString + 'eighteen'
      elsif left == 9
        numString = numString + 'nineteen'
      end
      # Since we took care of the digit in the ones place already,
      # we have nothing left to write.
      left = 0
    elsif write == 2
      numString = numString + 'twenty'
    elsif write == 3
      numString = numString + 'thirty'
    elsif write == 4
      numString = numString + 'forty'
    elsif write == 5
      numString = numString + 'fifty'
    elsif write == 6
      numString = numString + 'sixty'
    elsif write == 7
      numString = numString + 'seventy'
    elsif write == 8
      numString = numString + 'eighty'
    elsif write == 9
      numString = numString + 'ninety'
    end

    if left > 0
      numString = numString + '-'
    end
  end

  write = left # How many ones left to write out?
  left = 0 # Subtract off those ones.

  if write > 0
    if write == 1
      numString = numString + 'one'
    elsif write == 2
      numString = numString + 'two'
    elsif write == 3
      numString = numString + 'three'
    elsif write == 4
      numString = numString + 'four'
    elsif write == 5
      numString = numString + 'five'
    elsif write == 6
      numString = numString + 'six'
    elsif write == 7
      numString = numString + 'seven'
    elsif write == 8
      numString = numString + 'eight'
    elsif write == 9
      numString = numString + 'nine'
    end
  end

  if numString == ''
    # The only way "numString" could be empty is if
    # "number" is 0.
    return 'zero'
  end

  # If we got this far, then we had a number somewhere
  # in between 0 and 100, so we need to return "numString".
  numString
end

QUESTION 2: The second part of this code is just plain confusing me,
perhaps because I still can't figure out the first part which it builds
upon.

Any clarification & help would be greatly appreciated.

···

--
Posted via http://www.ruby-forum.com/.

Maybe this helps:

irb(main):001:0> 99/100
=> 0
irb(main):002:0> 250/100
=> 2
irb(main):003:0> 99.0/100
=> 0.99
irb(main):004:0> 250/100.0
=> 2.5

In the first two cases you are dealing with integer division.

For left = 99, write is *equal* to zero and "one hundred"
is *not* returned.

Regards,
Marcus

···

Am 11.06.2012 17:18, schrieb Michael Sung:

QUESTION 1: For example, if I choose 99 as my number, left = number, and
write = left/100, wouldn't write = 99/100? In that case, why would
write > 0 return 'one hundred'?

"QUESTION 2: The second part of this code is just plain confusing me,
perhaps because I still can't figure out the first part which it builds
upon."

The code example is not very elegant.

Keep this in mind when reading other people's code - their style may not
be beautiful.

Almost always, when you see lots of if/else, you may be better off using
case/when instead:

if write > 0
  if write == 1
    numString = numString + 'one'
  elsif write == 2
    numString = numString + 'two'
  end
end

Would be like this in case/when:

case write
when 1
  numString += 'one'
when 2
  numString += 'two'
end if write > 0 # though this if condition is not needed. Actually, I
argue that the if write > 0 in the original example is useless too. So
ebst omit the "if write > 0" also here.

···

--
Posted via http://www.ruby-forum.com/.

Hi,

Michael Sung wrote in post #1064054:

QUESTION 1: For example, if I choose 99 as my number, left = number, and
write = left/100, wouldn't write = 99/100? In that case, why would
write > 0 return 'one hundred'?

When you divide two integers in Ruby, you get an integer division rather
than a "normal" division. You probably remember doing long division in
elementary school. For example, 7 : 3 is 2 with a remainder of 1. This
is exactly how integer division works: 7/3 is 2. And 99/100 is 0.

So integer division always yields an integer rather than a float
(fractional number). If you want to do "normal" division, either the
dividend or the divisor has to be a float.

Michael Sung wrote in post #1064054:

QUESTION 2: The second part of this code is just plain confusing me,
perhaps because I still can't figure out the first part which it builds
upon.

The method basically calculates the hundreds, tens and ones of the
number and builds the name from it.

For example, the number 53 consists of 5 tens and 3 ones. The 5 tens
mean that the name begins with "fifty". And the 3 ones mean that the
name ends with "three".

···

--
Posted via http://www.ruby-forum.com/\.

The example is from a (very nice) book for programming novices
and case/when has not been introduced at that point...

Very interesting about the print version of this book is that
Chris Pine includes solutions for the exercises in two versions:
first a solution that corresponds to the current learning level
of the reader and then a more realistic and more elegant version.

Regards,
Marcus

···

Am 11.06.2012 18:16, schrieb Marc Heiler:

The code example is not very elegant.

Keep this in mind when reading other people's code - their style may not
be beautiful.

Almost always, when you see lots of if/else, you may be better off using
case/when instead: