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

For this I need a program to read in an unknown number of non-negative values from the user until a negative number is entered. Once a negative number is entered the program needs to print out three values: the largest, smallest, and average of the numbers.

This is what I have so far. I am unsure on how to get the program to recognize the largest and smallest.

#!/usr/bin/perl use Modern::Perl; my ( $total, $howmany, $largest, $smallest, $number, $average ) = ( 0, + 0, 0, 0, 0, 0 ); print "Please enter a number or -1 to end: "; chomp ( $number = <> ); while ( $number != -1 ) { $total += $number; $howmany ++; print "Please enter a number or -1 to end: "; chomp ( $number = <> ); } if ( $howmany == 0 ) { say "There were no numbers to average."; } else { say "The average of the numbers was ", $total / $howmany; say "The largest number was ", $largest; say "The smallest number was ", $smallest;

something like this is what I am thinking. for (my $x = 9999999; $x >= 1 ; $x-- ) { say $x } Im just not sure how to continue it through all the variables as they get larger

  • Comment on I am stuck on how to print the largest and smallest numbers from user inputted values. Any help is appreciated.
  • Download Code

Replies are listed 'Best First'.
Re: I am stuck on how to print the largest and smallest numbers from user inputted values. Any help is appreciated.
by Loops (Curate) on Nov 20, 2014 at 02:37 UTC

    So as you consider each number now, you're adding it to $total so that it is part of the final average. Similarly you need to keep the largest and smallest numbers you've seen so far. With each new number, after adding it to the $total, see if it qualifies as either the new largest or smallest, and update that value if so.

    You can construct your own "if" statements to see if the new number is greater than the current $largest or not. Or you could use List::Util which has a min (and a max) function which return the smallest (and largest) value of the list you pass in. For instance:

    use List::Util qw(min max); print max(4,8,2,33,1); # prints 33

    So each time you consider a new number you can update the $smallest number so far to either be the current value of $smallest, or the new number:

    $smallest = min ($smallest, $number);

    Unfortunately because $smallest is set to 0 at the start of your program, no value above zero will ever show up as the smallest input! You could start it off with a value of 10,000 and just hope nobody enters a number bigger than that. But a better way is to start $smallest off with the largest number possible, so that the first input it sees will naturally be the smallest-so-far. In Perl there is a funny notation for this largest number possible: '+inf', and for the smallest possible, minus infinity or '-inf'.

    Therefore you'd need to remove $smallest and $largest from where they are initialized to zero now, and add a line like:

    my ( $largest, $smallest ) = ('-inf', '+inf');

    So that the logic you use to find the largest and smallest is sure to find values that fit.

      As long as List::Util is being brought into play, why not use sum() as well as min() and max()? Just push entries to an array, say @numbers, as long as conditions for continued entry are met, then, after a test for no numbers at all having been entered,
          print 'The average of the numbers was ', sum(@numbers) / @numbers;
          print 'The largest number was ',  max @numbers;
          print 'The smallest number was ', min @numbers;
      (Admittedly, this approach may not be appropriate for homework.)

        Why even specify the list twice? Make it an odd count(-.

        require List::MoreUtils ; printf "min: %f ; max : %f\n" , List::MoreUtils::minmax @num ;

      Personally, I'd want to set the min and max to undef.

      I then have a min/max function that skips over undefs in the input list (rather than treating undef as zero). If everything in the list is undef, then the result is undef. Otherwise the min/max of the defined values is returned.

        Yeah, then you don't even really need to set them to undef, since as others have shown in their code there is already a decent way to test if it's the first iteration. Or you can just prime the values from the first input to begin with and start iterating from the second value. What I was describing was a more general idea that has the benefit of simplicity and avoiding an extra conditional check in every iteration.

Re: I am stuck on how to print the largest and smallest numbers from user inputted values. Any help is appreciated.
by Athanasius (Archbishop) on Nov 20, 2014 at 02:49 UTC

    Hello pcoady,

    First, please edit the title of your post to remove the <p> tags.

    Now to the assignment. Two preliminary matters:

    1. Your specification says: “until a negative number is entered.” But you are testing on only one negative number, namely -1. What if the user enters -2? You can fix this by changing the while condition to:

      while ( $number >= 0 )
    2. The closing brace is missing from the final else block.

    How to get the script to record the largest and smallest numbers? As an alternative to the solution proposed by Loops, you can treat the first user-entered number differently from all the others:

    while ($number >= 0) { $total += $number; $howmany++; if ($howmany == 1) { $largest = $number; $smallest = $number; } else { $largest = $number if $number > $largest; $smallest = $number if $number < $smallest; } print "Please enter a number or -1 to end: "; chomp($number = <>); }

    — a variation on the solution given by Anonymous Monk.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: I am stuck on how to print the largest and smallest numbers from user inputted values. Any help is appreciated.
by Anonymous Monk on Nov 20, 2014 at 02:44 UTC
    ... print "Please enter a number or -1 to end: "; chomp ( $number = <> ); $smallest = $number; # this is the smallest number we # saw so far $largest = $number; # it is also the largest while ( $number != -1 ) { $total += $number; $howmany += 1; $smallest = $number if $number < $smallest; $largest = $number if $number > $largest; ... chomp ( $number = <> ); } ...
    (most programmers would rather do it like Loops said)
Re: I am stuck on how to print the largest and smallest numbers from user inputted values. Any help is appreciated.
by Anonymous Monk on Nov 20, 2014 at 11:33 UTC
    Monks, don't give away the solution to an obvious homework assignment.