On 8/7/06, Daniel Schierbeck <daniel.schierbeck / gmail.com> wrote: > Rick DeNatale wrote: > > On 8/7/06, Daniel Schierbeck <daniel.schierbeck / gmail.com> wrote: > >> Ch Skilbeck wrote: > >> > def nextPowerOf2(n) > >> > raise "integer please" if !n.kind_of? Integer > >> > high = 0 > >> > count = 0 > >> > (0..n.size * 8 - 2).each {|b| count += n[b] ; high = b if n[b] != 0} > >> > 1 << high + (count > 1 ? 1 : 0) > >> > end > >> > >> Your question has already been answered by Simon, but I'd like to show > >> you how your code could be more Rubyesque. > >> > >> First off, method name are always lower_case_with_underscore, so > >> > >> def next_power_of_2(n) > >> > >> Ruby has the `unless' keyword, so > >> > >> raise "integer please" unless n.kind_of? Integer > >> > >> but you don't really have to check the argument's class -- just check if > >> the provided object responds to #to_int, or don't even check at all. > >> > >> raise "integer please" unless n.respond_to? :to_int > >> n = n.to_int > >> > >> Parallel assignment is cool > >> > >> high, count = 0, 0 > >> > >> I'd split the next part up, but that may just be me > >> > >> (0..(n.size * 8 - 2)).each do |b| > >> count += n[b] > >> high = b unless n[b] == 0 > >> end > >> > >> Just some thoughts > > > > Here's another take > > > > irb(main):016:0> class Fixnum > > irb(main):017:1> def next_power_of_2 > > irb(main):018:2> trial = 1 > > irb(main):019:2> trial <<= 1 while trial < self > > irb(main):020:2> return trial > > irb(main):021:2> end > > irb(main):022:1> end > > => nil > > irb(main):023:0> (-1..10).collect { | i | [i, i.next_power_of_2] } > > => [[-1, 1], [0, 1], [1, 1], [2, 2], [3, 4], [4, 4], [5, 8], [6, 8], > > [7, 8], [8, 8], [9, 16], [10, 16]] > > irb(main):024:0> > > > > This should be fairly fast since at first glance it's o(log2(n)) > > > > And it makes it a method of Fixnum > > > > Very nice. Better add it to Integer instead, though -- otherwise Bignums > won't have the method. Fair enough, and while I'm at it why not handle Floats as well class Integer def next_power_of_2 trial = 1 loop do return trial if trial >= self trial <<= 1 end end end class Float # Defer to Fixnum if not >= 0,0 and < 1.0 def next_power_of_2 ciel.next_power_of_2 if self >= 1 || self < 0 last_trial = 1.0 loop do trial = last_trial / 2.0 raise ArgumentError.new("#{self}.next_power_of_2 is not representable") if trial.zero? return last_trial if trial < self last_trial = trial end end end Note that some of the printed representations of some of those values of 2^n for negative n might look weird, but that's floating point math for you => 3.814697265625e-06 irb(main):016:0> t = 0.00003.next_power_of_2 => 3.0517578125e-05 irb(main):017:0> while t < 1.0 irb(main):018:1> p t irb(main):019:1> t *= 2.0 irb(main):020:1> end 3.0517578125e-05 6.103515625e-05 0.0001220703125 0.000244140625 0.00048828125 0.0009765625 0.001953125 0.00390625 0.0078125 0.015625 0.03125 0.0625 0.125 0.25 0.5 => nil -- Rick DeNatale