--Boundary-00 ywrHn/OeCBxkgG
Content-Type: Multipart/Mixed;
boundaryoundary-00 ywrHn/OeCBxkgG"
--Boundary-00 ywrHn/OeCBxkgG
Content-Type: text/plain;
charset tf-8"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Here's my first solution, attached and pastied here:
http://pastie.caboo.se/149976
Its basically a binary search, repeatedly calculating the NVP and adjusting
lower and upper bounds. Not too complicated, so let me just note a couple
things:
* Line 12 could have been a mirror of line 10, but I wanted to emphasize the
symmetry.
* Rationals are used throughout to ensure accuracy.
* The "+ 1" on line 10 prevents 0 from being a fixed point.
* The given accuracy guarantees the result will be within 1 / 10 ** [accuracy]
of the true answer. This is not the same thing as having [accuracy] number of
correct digits. (Though the program could be made to do that if the guesses
fell on negative powers of ten).
I haven't done all that many quizzes, but those I have were very enjoyable.
Thank you James.
-Jesse Merriman
--Boundary-00 ywrHn/OeCBxkgG
Content-Type: application/x-ruby;
name rr.rb"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename rr.rb"
#!/usr/bin/env ruby
# Ruby Quiz 156: Internal Rate of Return
# Jesse Merriman
require 'rational'
# Guess a new number between a lower and upper bound.
def guess lower, upper
if upper 1.0/0.0
lower < 0 ? 0.to_r : (lower + 1) * 2
elsif lower 1.0/0.0
- guess(-upper, -lower)
else
(lower + upper) / 2
end
end
# Calculate the IRR to within 1 / 10**accuracy
def irr cash_flows, accuracy
nvp ambda do |irr|
t
cash_flows.inject { |sum, c| t + ; sum + c / (1 + irr) ** t }
end
lower, upper 1.to_r, 1.0/0.0
while (lower - upper).abs > Rational(1, 10 ** accuracy)
g uess lower, upper
nvp[g] > 0 ? lower : upper
end
(lower + upper) / 2
end
class String
def to_r
if m ^(\-?\d+)$/.match(self)
m[1].to_i.to_r
elsif m ^(\-?\d+)\.(\d+)$/.match(self)
m[1].to_i + Rational(m[2].to_i, 10 ** m[2].length)
elsif m ^(\-?\d+)\s*\/\s*(\d+)$/.match(self)
Rational m[1].to_i, m[2].to_i
else
raise StandardError, "Can't parse #{self} to a Rational"
end
end
end
if __FILE__ $0
cash_flows RGV[0..-2].map { |x| x.to_r }
accuracy RGV[-1].to_i
if cash_flows.inject { |sum, x| sum + x } < 0
puts 'Cannot solve with net negative.'
else
i rr cash_flows, accuracy
puts "irr: #{i} (#{i.to_f})"
end
end
--Boundary-00 ywrHn/OeCBxkgG--
--Boundary-00 ywrHn/OeCBxkgG--