My solution, looping the Bolzano's Theorem:


class Irr

  attr_accessor :data, :irr

  def initialize(data)
    @data = data
    @irr = 0
    irr_calculus
  end

  def npv_calculus(rate)
    npv = 0
    @data.each do |c|
      t = @data.index(c)
      npv = npv + c / (1 + rate)**t
    end
    npv
  end

  def irr_calculus
    r1 = 0.0
    r2 = 1.0
    npv1 = npv_calculus(r1)
    npv2 = npv_calculus(r2)

    # calcule initial interval
    while npv1*npv2 > 0
      r1 = r1 + 1
      r2 = r2 + 1
      npv1 = npv_calculus(r1)
      npv2 = npv_calculus(r2)
    end

    # halfing interval to achieve precission
    value = 1
    while value > (1.0/10**4)
      r3 = (r1+r2)/2
      npv3 = npv_calculus(r3)
      if npv1*npv3 < 0
        r2 = r3
        npv2 = npv3
      else
        r1 = r3
        npv1 = npv3
      end
      value = (r1-r2).abs
    end

    @irr = (r1*10000).round/10000.0
  end

end


data = [-100, 30, 35, 40, 45]
i = Irr.new(data)
puts i.irr
-- 
Posted via http://www.ruby-forum.com/.