#!/usr/bin/perl require 5.003; use strict; die "Usage: irr_del <data file>\n" if $#ARGV < 0; my $iters_max = 20; # maximum number of # iterations my $epsilon = 1.0e-6; # jump out of loop # if change < $epsilon my $u = 0.0; # initial guess. interest = exp(-$u) - 1 my(@pos_d, @pos_t, @neg_d, @neg_t, $dollars, $time, $pos, $d_pos, $neg, $d_neg, $iters, $delta, $i, $tmp); while(<>) { chomp; ($dollars, $time) = split; write; switch: { push(@pos_d, $dollars), push(<pos_t, $time), last if $dollars > 0.0; push(@neg_d, -$dollars), push(@neg_t, $time), last if $dollars < 0.0; die "Dollar amount cannot = \$0.00 !...\n"; } } die "\nCan't calculate. Need income AND expenses!\n=" unless $#pos_d >= 0 and $#neg_d >= 0; for($iters = $iters_max; $iters > 0; $iters--) { $pos = $d_pos = $neg = $d_neg = 0.0; for($i = 0; $i <= $#pos_d; $i++) { $pos += ($tmp = $pos_d[$i] * exp($u * $pos_t[$i])); $d_pos += $tmp * $pos_t[$i]; } for($i = 0; $i <= $#neg_d; $i++) { $neg += ($tmp = $neg_d[$i] * exp($u * $neg_t[$i])); $d_neg += $tmp * $neg_t[$i]; } $delta = log($neg / $pos) / ($d_neg / $neg - $d_pos / $pos); last if abs($delta) < $epsilon; # Newton # converged $u -= $delta; # next guess } if($iters > 0) { printf "\nIRR = %.4f%% (discrete) = %.4f%% ", printf "(continuous) after %u " printf "iteration%s.\n", 100.0 * (exp(-$u) - 1.0), -100 * $u, $iters_max - $iters + 1, $iters_max - $iters == 0 ? '' : 's'; } else { printf "irr doesn't converge in $iters_max", printf " iterations\n"; } format STDOUT_TOP = Income($) Time (yr) ========= ========= . format STDOUT = @######.## @##.## $dollars, $time .