From: Jesse Merriman Date: 2008-02-11T03:38:56+09:00 Subject: [SOLUTION][QUIZ] Internal Rate of Return (#156) --Boundary-00=_HT0rHOMwZW30Cy7 Content-Type: Multipart/Mixed; boundary="Boundary-00=_HT0rHOMwZW30Cy7" --Boundary-00=_HT0rHOMwZW30Cy7 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Content-Disposition: inline Here's a second solution from me: http://pastie.caboo.se/150029 Well, maybe its a half-solution, since it defers the real work to an external program. A while ago I wrote some code for communicating with a Maxima process [1]. This solution uses it to directly solve the NVP equation (for both real and complex IRRs). Note that there is a bug in version 0.0.4 of my library that incorrectly returns only the first line of a multi-line result, so it doesn't always work. I've had it fixed in a newer version for a while, but never released it. I'll try to get it up within the next few days. [1] http://www.jessemerriman.com/project/ltf --Boundary-00=_HT0rHOMwZW30Cy7 Content-Type: application/x-ruby; name="irr_maxima.rb" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="irr_maxima.rb" #!/usr/bin/env ruby # Ruby Quiz 156: Internal Rate of Return # Jesse Merriman, Maxima version require 'ltf' include LTF class Array def map_with_index mapped = [] each_with_index { |x, i| mapped << yield(x, i) } mapped end end if __FILE__ == $0 cash_flows = ARGV[0..-2] accuracy = ARGV[-1].to_i eq = '0 = ' + cash_flows.map_with_index { |x, i| "#{x}/(1+irr)^#{i}" }.join(' + ') max = Maxima.new "fpprec: #{accuracy};" max.puts "res: solve([#{eq}], [irr]);" sols = [] num_sols = max.puts('length(res);').to_i num_sols.times { |i| sols << max.puts("bfloat(res[#{i+1}]);") } real_sols, complex_sols = [], [] sols.each do |s| if /%i/.match(s) complex_sols << s else real_sols << s end end puts 'Real solutions:' puts ' ' + real_sols.join("\n ") puts 'Complex solutions:' puts ' ' + complex_sols.join("\n ") max.quit end --Boundary-00=_HT0rHOMwZW30Cy7-- --Boundary-00=_HT0rHOMwZW30Cy7--