Preface

This is a series of tutorials centered around using Ruby in Object-Oriented mode

First, let’s check if we have a functioning Ruby compiler and ask for the version information.

puts "Hello, World!"
puts RUBY_DESCRIPTION
## Hello, World!
## ruby 2.5.3p105 (2018-10-18 revision 65156) [x64-mingw32]

Programming Structures

Now lets explore the key programming structure

Variable

Variables are basically a container for data. In Ruby the context of the variable declaration will determine the variable type. Ruby uses Duck typing, i.e. if it looks like a duck, quacks like a duck, swims like a duck and walks like a duck, we call it a duck)

a = 1 + 1
b = "1" + "1"
c = "123".to_i + "456".to_i 
d = 1234   * 10000000000000000000000 + 123 
e = 1234.5 * 10000000000000000000000 + 123 
f = Rational(3) / 27

[a,b,c,d,e,f].each {|x| 
  print x.class,": ", x, "\n"
}
## Integer: 2
## String: 11
## Integer: 579
## Integer: 12340000000000000000000123
## Float: 1.2345e+25
## Rational: 1/9

Since each variable is an object, it comes with a set of methods for operating on the
* Input/ Output functions

# a = gets
a = "1.0001\n"
b = a.chomp!
c = b.to_i

[a, b, c].each { |x|
   puts "%s: >%s<" %  [x.class, x.to_s]
}
## String: >1.0001<
## String: >1.0001<
## Integer: >1<
class Person
  attr_accessor :name, :age

  def initialize(name,age)
   @name = name
   @age = age
  end
  
  def to_s
     [@name, @age.to_s].join(" ")
  end
end

a = Person.new("Bill",50)
puts a
a.name = "Nam"
a.age += -25
puts a
## Bill 50
## Nam 25
  • Functions / method

    • Changing / interacting with attributes
    • Returning a corresponding values
puts Math.sin(Math::PI/2)
## 1.0
  • Control structures:
    • If vs While
      • if is a single branch
      • continuous conditional processes

Let’s say we have a random function.

\[y+ x^2\] and we are not certain about our skills to integrate it. \[\eqalign{\int_3^5 x^2 dx &= \left.{x^3\over 3}\right]_3^5&= {5^3 -3^3\over 3}\\&={125-27\over 3}&={98\over 3}=32.66667\\}\]

We can use Ruby to check our answer using the trapezoid rule. However, the trapezoid rule is more accurate as smaller slices are used.

Testing a series of decreasing intervals will help suggest the true value.

require 'bigdecimal'
require 'bigdecimal/util'

def func(x)
    return(x*x)
end


def integrate1(start,ending,width)
   area = 0.0
   x = start
   while x < ending
     area += 0.5 * width *
          (func(x) + func(x + width))
     x += width
   end
   return area
end

def integrate2(start,ending,width)
   area = 0.0
   x = start + 0.0
   lastval = func(x)
   halfwidth = width / 2.0
   while x < ending
     nextval = func(x + width)
     area += halfwidth*(nextval + lastval)
     lastval = nextval
     x += width
   end
   return area
end

def integrate3(start,ending,width)
   area = 0.0
   x = start + 0.0
   lastval = func(x)
   while x < ending
     nextval = func(x + width)
     area += (lastval + nextval)
     lastval = nextval
     x += width
   end
   area *= width / 2.0 
   return area
end

def integrate4(start,ending,width)
   area = 0.0.to_d
   x = start + 0.0.to_d
   dx = width.to_d
   lastval = func(x)
   while x < ending
     nextval = func(x + dx)
     area += (lastval + nextval)
     lastval = nextval
     x += dx
   end
   area *= dx / 2.0 
   return area
end

4.times do |test|
interval = 1.0
puts "Testing integrate#{test+1}()"
puts "Interval     Result"
t = Time.now
9.times do 
  answer = case test+1
  when 1 then integrate1(3,5,interval)
  when 2 then integrate2(3,5,interval)
  when 3 then integrate3(3,5,interval)
  when 4 then integrate4(3,5,interval)
  end
  
  puts "%10.8f %20.18f" % [interval,answer]

  STDOUT.flush
  interval /= 10
end
puts "Completed in #{Time.now - t} seconds"
puts
end
## Testing integrate1()
## Interval     Result
## 1.00000000 33.000000000000000000
## 0.10000000 35.220499999999994145
## 0.01000000 32.917200499999616170
## 0.00100000 32.666667000000146004
## 0.00010000 32.669166720016306726
## 0.00001000 32.666916667106242755
## 0.00000100 32.666666669090481889
## 0.00000010 32.666666659025402453
## 0.00000001 32.666667061315479259
## Completed in 32.207715 seconds
## 
## Testing integrate2()
## Interval     Result
## 1.00000000 33.000000000000000000
## 0.10000000 35.220499999999994145
## 0.01000000 32.917200499999616170
## 0.00100000 32.666667000000146004
## 0.00010000 32.669166720016306726
## 0.00001000 32.666916667106242755
## 0.00000100 32.666666669090481889
## 0.00000010 32.666666659025402453
## 0.00000001 32.666667061315479259
## Completed in 26.514281 seconds
## 
## Testing integrate3()
## Interval     Result
## 1.00000000 33.000000000000000000
## 0.10000000 35.220500000000001251
## 0.01000000 32.917200499999630381
## 0.00100000 32.666667000000167320
## 0.00010000 32.669166720016200145
## 0.00001000 32.666916667106235650
## 0.00000100 32.666666669090176356
## 0.00000010 32.666666659026489583
## 0.00000001 32.666667061330144861
## Completed in 23.18573 seconds
## 
## Testing integrate4()
## Interval     Result
## 1.00000000 33.000000000000000000
## 0.10000000 32.670000000000001705
## 0.01000000 32.666699999999998738
## 0.00100000 32.666666999999996790
## 0.00010000 32.666666669999997907
## 0.00001000 32.666666666700002963
## 0.00000100 32.666666666666998253
## 0.00000010 32.666666666666671404
## 0.00000001 32.666666666666664298
## Completed in 612.425761 seconds