stankuli has asked for the wisdom of the Perl Monks concerning the following question:

below is my script. the incrementation loop works correctly until it hits 5.9 then it increments incorrectly just there. sample output follows the code.

#!/usr/bin/perl # zeta.pl c.2011 stan kulikowski ii, stankuli@etherways.com, pensacol +a, fl 32514 $SERIES_DEPTH = 1000000; &QUERY_DIRICHLET; sub QUERY_DIRICHLET { my $POWERS = 1; my $PRECISION = 0; print "\n Dirichlet's zeta function. \n"; my $OK = 0; until ($OK) { print " How many powers : "; chop($POWERS = <>); $POWERS = int $POWERS; ($POWERS > 1) ? $OK = 1 : print " value must be greater than 1 \n" +; } # until $OK # $OK = 0; until ($OK) { print " To what precision : "; chop($PRECISION = <>); ($PRECISION < 1 && $PRECISION > 0) ? $OK = 1 : print " value must +be between 1 and 0 \n"; } # until $OK # &DIRICHLET ($POWERS,$PRECISION); print "\n\n"; } # QUERY_DIRICHLET # sub HARMONIC_SERIES { my ($POWER) = @_; my $RESULT = 1; my $SERIES = $SERIES_DEPTH; while ($SERIES > 1) { $RESULT += 1/($SERIES-- **$POWER); } # while ($SERIES > 1) # return $RESULT; } # HARMONIC_SERIES # sub DIRICHLET { my ($POWERS,$PRECISION) = @_; my $POWER = 2; print "\n\n\t Power \t Dirichlet's zeta result (harmonic series dep +th = $SERIES_DEPTH)\n\n"; while ($POWER < $POWERS+1) { print "\t $POWER \t " . &HARMONIC_SERIES ($POWER) . " \n"; $POWER += $PRECISION; # problem here at 5.9? } # while ($POWER <= $POWERS) # } # DIRICHLET # # eof zeta.pl

here is what the output looks like:

Dirichlet's zeta function. How many powers : 6 To what precision : 0.1 Power Dirichlet's zeta result (harmonic series depth = 1000 +000) 2 1.64493306684877 2.1 1.56021630515022 2.2 1.49054320392715 2.3 1.43241778712389 2.4 1.38334285599691 2.5 1.34148725658587 2.6 1.30547780891302 2.7 1.27426464440048 2.8 1.24703142229228 2.9 1.22313389528938 3 1.20205690315031 3.1 1.18338365210598 3.2 1.16677337098058 3.3 1.15194479471816 3.4 1.13866377572624 3.5 1.12673386731579 3.6 1.11598907912243 3.7 1.10628824146401 3.8 1.09751057645852 3.9 1.08955218466995 4 1.08232323371086 4.1 1.07574569034329 4.2 1.06975147723364 4.3 1.0642809643257 4.4 1.05928172597973 4.5 1.05470751076137 4.6 1.0505173825665 4.7 1.04667500069907 4.8 1.04314801333513 4.9 1.03990754404931 5 1.03692775514334 5.1 1.03418547468746 5.2 1.03165987667789 5.3 1.0293322056832 5.4 1.02718553892034 5.5 1.02520457995467 5.6 1.02337547922702 5.7 1.02168567742621 5.8 1.02012376838834 5.9 1.01867937874473 5.99999999999999 1.01734306198444 6.09999999999999 1.0161062049622 6.19999999999999 1.01496094518522 6.29999999999999 1.0139000974628 6.39999999999999 1.01291708871218 6.49999999999999 1.01200589988852 6.59999999999999 1.01116101415427 6.69999999999999 1.01037737052638 6.79999999999999 1.00965032234471 6.89999999999999 1.00897559999333 6.99999999999999 1.00834927738192

Replies are listed 'Best First'.
Re: incrementation loop fails?
by ikegami (Patriarch) on Sep 29, 2011 at 19:11 UTC

    1/10 is a periodic number in binary just like 1/3 is a periodic number in decimal. It would take infinite storage to store it as floating point number.

    You're magnifying the error by applying it numerous times. Just round the numbers using sprintf where needed.

Re: incrementation loop fails?
by keszler (Priest) on Sep 29, 2011 at 17:53 UTC
      Howdy!

      That only works when the precision is 0.1; that cannot be assumed as it is user input. Using printf to limit the precision of the output is one way, but you have to be careful with your limits, based on the user's specified precision. One digit would not be helpful if the precision were 0.01, to haul out an obvious example.

      yours,
      Michael
      Why divide, when multiplication handles irregular strides and avoids the need for sprintfs?
      sub DIRICHLET { my ($POWERS,$PRECISION) = @_; print "\n\n\t Power \t Dirichlet's zeta result (harmonic series dep +th = $SERIES_DEPTH)\n\n"; my $start = 2; my $i = 0; while ( (my $POWER = $start + $PRECISION*$i++) < $POWERS+1) { print "\t $POWER \t " . &HARMONIC_SERIES ($POWER) . " \n"; } } # DIRICHLET #
Re: incrementation loop fails?
by AnomalousMonk (Archbishop) on Sep 30, 2011 at 04:09 UTC
Re: incrementation loop fails?
by stankuli (Initiate) on Sep 30, 2011 at 21:54 UTC

    the problem i reported was this loop executed correctly for about 40 iterations then it incremented $POWER incorrectly on the 41st iterations, then continues on correctly for at least 20 more iterations, but with the incorrect value after 41.

    while ($POWER < $POWERS+1) { print "\t $POWER \t " . &HARMONIC_SERIES ($POWER) . " \n"; $POWER += $PRECISION; # problem here at 5.9? } # while ($POWER <= $POWERS) #

    someone called kennethk suggested this kludge which corrected the problem.

    my $START = 2; my $EACH = 0; while ((my $POWER = $START + $PRECISION*$EACH++) < $POWERS+1) { print "\t $POWER \t " . &HARMONIC_SERIES ($POWER) . " \n"; }

    apparently, perl is intended to allow for variable incrementation within loops as i had originally written it. it works for the first 40 iterations, and only fails on the 41st time through. that function call &HARMONIC_SERIES is rather putting some effort on the cpu, it doing the zeta exponential calculations about 10 million times, but the bug shows even at 1 million or 100 thousand series depths. so, i suspect that there must be some sort of memory overrun in the hardware causing the simplest iteration of the variable.

    there is nothing wrong with kludges when they are necessary. this one seems to allocate the variable to count each iteration outside of the loop, then reallocates $POWER variable after each iteration, so starts off with fresh contents recalculated with the increments.

    the dirichlet zeta calculations are an exercise in pure mathematics, and the lengthy decimal outputs are known as the open representation of the irrational convergence on to the limits being approximated by millions of incremental calculations. these are the correct results which match published values in books on this subject.

    Power Dirichlet's zeta result (harmonic series depth = 1000 +0000) 2 1.64493396684722 2.1 1.56021651535977 2.2 1.49054325318119 2.3 1.43241779869829 2.4 1.38334285854823 2.5 1.34148725710385 2.6 1.30547780899489 2.7 1.27426464440048 2.8 1.24703142229228 2.9 1.22313389528938 3 1.20205690315031 3.1 1.18338365210598 3.2 1.16677337098058 3.3 1.15194479471816 3.4 1.13866377572624 3.5 1.12673386731579 3.6 1.11598907912243 3.7 1.10628824146401 3.8 1.09751057645852 3.9 1.08955218466995 4 1.08232323371086 4.1 1.07574569034329 4.2 1.06975147723364 4.3 1.0642809643257 4.4 1.05928172597973 4.5 1.05470751076137 4.6 1.0505173825665 4.7 1.04667500069907 4.8 1.04314801333513 4.9 1.03990754404931 5 1.03692775514334 5.1 1.03418547468746 5.2 1.03165987667789 5.3 1.0293322056832 5.4 1.02718553892034 5.5 1.02520457995467 5.6 1.02337547922702 5.7 1.02168567742621 5.8 1.02012376838834 5.9 1.01867937874473 6 1.01734306198444 6.1 1.0161062049622 6.2 1.01496094518522 6.3 1.0139000974628 6.4 1.01291708871218 6.5 1.01200589988852 6.6 1.01116101415427 6.7 1.01037737052638 6.8 1.00965032234471 6.9 1.00897559999333

    my thanks for your assistance in getting this part of the program to operate as it needs to. i may be back as the next part of the program does the riemann zeta calculations using complex numbers to find the nontrivial zeros in the function output.