#!/usr/bin/perl # Lagrange-Method to regressively calculate the value of any # element of a sequence, by using the input values of already # existing elements of the sequence # this could be easily modulized as a perl module # for simplicity it is kept in one file # # copyleft 2007 by dennisg # use strict; our @elements; # 5.2, 3,-4, 0, 19.1 my $x; my $product; my $sum = 0; my $steps = 0; my $e = 0; # main program ---------------- # print this only if no arguments are given: print "usage: lagrange.pl arg1 [arg2] following_args where arg1 = N. step of the sequence to calculate (for N=0 it's the first of the following_args) if arg2 is set to 'steps' the intermediate steps are printed the arguments following after that will be used as the sequence's values example: lagrange.pl 3 steps 2 4 6 8 10" if !$ARGV[0]; # put the value from the beginning of our arguments as # the x value we want to calculate # and remove it from the beginning of the array $x = shift @ARGV; # check if this argument equals "steps" # and remove it from the array if yes $steps = shift @ARGV if $ARGV[0] eq "steps"; # begin iterating through the rest of our arguments foreach (@ARGV) { # just match correctly formed numbers or math. fractions if ($_ =~ /^([-]?[0-9]+[.]?[\/]?[0-9]?)$/) { # print it, if we want to see the steps: print "adding element Index: $e := $_\n" if $steps; # use "eval" to evaluate math. fractions $elements[$e++]=eval($_); } } # print the result print("a($x) = ".lagrange($x)."\n"); # ----------------------------- # function to calculate lagrange - one input argument for the position of x sub lagrange { # set the first input argument to $x and don't care about the rest $x = shift; for (my $i = 0; $i <= $#elements; $i++) { # print what we are doing, if "steps" is set print "i = $i :\n" if $steps; # we need to have the default product variable set to 1 # otherwise we have a multiplication by zero the first time # which we don't want of course! $product = 1; # iterate through the j's for (my $j = 0; $j <= $#elements; $j++) { # but just do something if j is not the same as i if ($i != $j) { # multiplicate with the next step $product=$product*(($x-$j)/($i-$j)); # print what we are doing, if "steps" is set print "\tj = $j\tproduct: $product * ($x-$j)/($i-$j)\n" if $steps; } } # print what we are doing, if "steps" is set print " current sum: $sum + $elements[$i] * $product" if $steps; # multiplicate the whole product with the current element $sum=$sum+$elements[$i]*$product; # also print the result of this sum if "steps" is set print " = $sum\n--------------\n" if $steps; } return $sum; } exit 0;