RSS

>Integer Division with Modulus in Ruby, using Linear and Binary Search

26 Jun

>

I was recently chatting with someone about algorithms, and we were talking about efficient algorithm for implementing integer division with modulus, and how to make it efficient for large integers.

The following code snippet shows a class that implements two division methods, linear and binary. I wonder if there is a more elegant way to implement binary, please feel free to post to comments if there are. Also, any other faster methods are welcome.

# divide.rb
# Integer Divider Class that implements two algorithms for finding the 
# division result and modulus of two integers.
class IntegerDivider
  def self.linear n, d
     raise 'Cant divide by zero!' if (d == 0)
     multiplier = n * d = n)
     i -= 1 if (i*d > n)
     return multiplier * i, n - i*d, i
  end

  def self.binary n, d
     raise 'Cant divide by zero!' if (d == 0) 
     multiplier = n * d = n) 
     return multiplier * i, 0 if (i*d == n) 
     i /= 2; j = i; cnt = 0
     begin
       j /= 2; cnt += 1
       sign = ((i + j)*d > n) ? 0 : 1
       i = i + sign * j 
     end until (i*d  n) 
     return multiplier * i, n - i*d, cnt
  end
  
  def self.divide(how, numerator, denominator)
    before = Time.now.to_f
    (result, remainder, iterations) = self.send(how, numerator, denominator)
    after = Time.now.to_f
    puts "#{sprintf('%8.3f',(after - before)*1000)}ms #{how}" + 
         " (#{sprintf '%10d', iterations} iterations):  #{numerator} / " +
         " #{denominator} = #{result}, mod #{remainder}"
    return [result, remainder]
  end
end

[:linear, :binary].each do |method|
  ARGV.each do |numerator|
    IntegerDivider.divide(method, numerator.to_i, 3)    
  end
end

And some results of running it. Of course for large number like 100000000, binary search takes 24 iterations to get the answer, while linear … well 100000000. The total speed difference at such large number is big: 1524ms/0.012ms = 127,000.

> ruby divide.rb 10 100 1000 20000 100000000
   0.006ms linear (         3 iterations):  10 /  3 = 3, mod 1
   0.003ms binary (         1 iterations):  10 /  3 = 3, mod 1
   0.003ms linear (        33 iterations):  100 /  3 = 33, mod 1
   0.003ms binary (         5 iterations):  100 /  3 = 33, mod 1
   0.017ms linear (       333 iterations):  1000 /  3 = 333, mod 1
   0.004ms binary (         8 iterations):  1000 /  3 = 333, mod 1
   0.411ms linear (      6666 iterations):  20000 /  3 = 6666, mod 2
   0.006ms binary (        11 iterations):  20000 /  3 = 6666, mod 2
1524.712ms linear (  33333333 iterations):  100000000 /  3 = 33333333, mod 1
   0.012ms binary (        24 iterations):  100000000 /  3 = 33333333, mod 1
About these ads
 
Leave a comment

Posted by on June 26, 2010 in Ruby on Rails, Technology

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: