Math Tricks

Quick question. When I run:

#!/usr/bin/env ruby

class RPNCalc
  def initialize(stack = [ ])
    @stack = stack
  end
  
  def push(number)
    if number.kind_of? Numeric
      @stack.push(number)
      return @stack[-1]
    else
      return nil
    end
  end
  
  def add; return binary { |l, r| l + r } end
  def sub; return binary { |l, r| l - r } end
  def mul; return binary { |l, r| l * r } end
  def div; return binary { |l, r| l / r } end
  
  private
  
  def unary(&op)
    if @stack.size < 1
      raise "Insufficient elements on stack for operation."
    end
    
    return push( op.call( @stack.pop ) )
  end
  
  def binary(&op)
    if @stack.size < 2
      raise "Insufficient elements on stack for operation."
    end
    
    return push( op.call( *@stack.slice!(-2, 2) ) )
  end
end

calc = RPNCalc.new
puts calc.push(3)
puts calc.push(5)
puts calc.add
puts calc.push(2)
puts calc.mul
puts calc.push(2)
puts calc.push(3)
puts calc.add
puts calc.div

__END__

I see 3 as the last output when I expect to see 3.2. Why is that?

James Edward Gray II

P.S. I wanted to collapse those math defs to one line for easy reading and found the semicolon trick used above. Is that the only way to do it, or is there a method similar to if ... then ... end?

James Edward Gray II wrote:

Quick question. When I run:

[snip]

I see 3 as the last output when I expect to see 3.2. Why is that?

If you divide two integers, you get an integer (with Ruby). So instead of say "2" and "3", say "2.0" and "3.0".

···

--
Jamis Buck
jgb3@email.byu.edu
http://www.jamisbuck.org/jamis

The other questions were answered pretty well, so I'll just answer the last one. You can either use the semicolon, or specify an empty parameter list:

def add; return binary { |l, r| l + r } end
def add() return binary { |l, r| l + r } end

The empty parameter list looks cleaner, imho, though it *is* one character longer.

cheers,
Mark

···

On Sep 29, 2004, at 3:08 PM, James Edward Gray II wrote:

Quick question. When I run:

<snip>

James Edward Gray II

P.S. I wanted to collapse those math defs to one line for easy reading and found the semicolon trick used above. Is that the only way to do it, or is there a method similar to if ... then ... end?

Jamis Buck ha scritto:

James Edward Gray II wrote:

Quick question. When I run:

[snip]

I see 3 as the last output when I expect to see 3.2. Why is that?

If you divide two integers, you get an integer (with Ruby). So instead of say "2" and "3", say "2.0" and "3.0".

or do:
require 'mathn'

to get magic integration of every numerical thingy:
>> 1/2
=> 1/2

Thanks to all for the help.

James Edward Gray II

···

On Sep 29, 2004, at 5:27 PM, Mark Hubbart wrote:

The other questions were answered pretty well, so I'll just answer the last one. You can either use the semicolon, or specify an empty parameter list:

def add; return binary { |l, r| l + r } end
def add() return binary { |l, r| l + r } end

The empty parameter list looks cleaner, imho, though it *is* one character longer.

Or:
def div; binary { |l, r| l.to_f / r } end

···

On Sep 29, 2004, at 4:15 PM, Jamis Buck wrote:

I see 3 as the last output when I expect to see 3.2. Why is that?

If you divide two integers, you get an integer (with Ruby). So instead of say "2" and "3", say "2.0" and "3.0".