I have a school assignment I need help with. Now, I know what you're thinking, but my teacher is out of town and hasn't answered my e-mails, and my other classmates have no clue how to solve this problem. A few pointers and tips would be greatly appreciated!
The assignment is this:
We're supposed to create an array, populate it with 20 to 30 random integers in the range of 1-100. Then, by the help of subroutines, we're supposed to calculate the average of these numbers.
The problem occurs when I'm calling the subroutine back, which gives me either answer 0 or the "Illegal division by 0" error. The code I have right now is this:
#! /usr/bin/perl -w
use warnings;
use strict;
# Declaring the scalar variables and arrays.
my @AllNumbers;
# Create random data set of between 20 to 30 measures used for the 100 random intigers.
my $random_number = int( rand( 31 - 20 ) ) + 20;
# Create random data set of 100 intigers.
for ( my $i = 0 ; $i <= $random_number ; $i++ ) {
$AllNumbers[$i] = int( rand( 100 - 1 ) );
}
# Print the 20 to 30 random numbers (range 1 - 100).
print("Your random numbers are: \n@AllNumbers");
sub average {
my $ArrayAverage = @_;
for (@_) {
my $total += $_;
}
return $ArrayAverage / $random_number;
} ## end sub average
# Print the mean/average of the 20-30 numbers.
print( "\n\nThe average of those random numbers is: ", &average, "\n\n" );
Now, as I said, I'd like to solve this problem myself, and I've spent an entire two days with this, but can't seem to solve it no matter what I do. Any tips would be greatly appreciated. P.S. It should be mentioned that we're not supposed to use any modules/plugins.
So the solution is that you simply need to pass the @AllNumbers array to the &average() when being called: print ("\n\nThe average of those random numbers is: ", &average(@AllNumbers), "\n\n"); This should work fine ;) Good luck!
We shall use a loop and sum up all values of the array. Then we shall divide the sum with the number of elements in the array, this shall produce average of all values of the array.
Example 1 to calculate the average using arrays First, create an array with values and run. the for loop to find the sum of all the elements of the array. Finally, divide the sum with the length of the array to get the average of numbers.
Then, we use a for loop to input the numbers from the user and store them in the num array. Every time a number is entered by the user, its value is added to the sum variable. By the end of the loop, the total sum of all the numbers is stored in sum . After storing all the numbers, average is calculated and displayed.
There's a couple of style points I'd address first:
put your sub at the beginning (or if you must, at the end). Having it in the middle of code is messy.
Don't call subroutines with &
- it's bad style, and makes for some strange behaviour. In your case: &average
is effectively being called with no arguments. It's bad in general though, don't use it unless you know specifically why you're doing so. (It does have some uses, but you'll know when you see them - and you won't in your early learning of perl
).
Capitalisation of arrays like that isn't good form, because that's how modules/packages are named. Stick with lower case variables if you can.
your for loop is a C style, which works, but would be better written for ( 1..$random_number ) {
as you don't need the iterator.
You don't need -w
on the shebang line, because you have use warnings
. use warnings;
is the better way of doing it.
calling your variable $random_number
isn't very helpful - we can see that, because it's assigned the result for rand
. Call it what it's used for - like $number_of_elements
.
given you only really need to use $random_number
once, you probably don't need to stick it in a variable. You can, if you feel it assists readability (that's a matter of taste - in good programming, being clear and readable is the only thing that's really important - most memory/performance things are premature optimisations given the state of compilers today.)
Your core problem here though, is this:
my $ArrayAverage = @_;
That sets $ArrayAverage
to the number of elements in the list. This will always be the same as $random_number
, because that's how many times you iterate.
You iterate elements here, but don't actually use $total
.
for (@_) {
my $total += $_;
}
So here - you're returning number of elements in array divided by number of elements in array.
return $ArrayAverage / $random_number;
But the really important thing is - none of this matters, because you're invoking it with &average
which isn't actually sending any arguments. So you're just putting in zero, and getting out zero.
It may be useful to know - an array in a scalar context returns the number of elements, so computing your average is as simple as:
my $sum;
$sum += $_ for @AllNumbers;
print( "\n\nThe average of those random numbers is: ", $sum / @AllNumbers, "\n\n" );
This'll produce a long decimal - if you need to format it, you can use printf
or sprintf
.
printf( "\n\nThe average of those random numbers is: %02.2f \n\n", $sum / @AllNumbers);
So I would rewrite it slightly as this:
#!/usr/bin/perl
use warnings;
use strict;
# Declaring the scalar variables and arrays.
my @all_numbers;
#repeat 20 + random 11 times - so 20-30
for ( 1 .. 20 + int rand 11 ) {
push ( @all_numbers, int rand 99 );
}
# Print the 20 to 30 random numbers (range 1 - 100).
print("Your random numbers are: \n@all_numbers\n");
#calculate sum of elements
my $sum;
$sum += $_ for @all_numbers;
print "Sum: $sum count: ", scalar @all_numbers, "\n";
# Print the mean/average of the 20-30 numbers.
printf( "\n\nThe average of those random numbers is: %02.2f \n\n", $sum / @all_numbers);
Writing it in idiomatic Perl would give you something like this:
#!/usr/bin/perl
use warnings;
use strict;
my @numbers;
my $how_many = int(rand 11) + 20;
push @numbers, int(rand 100) + 1 for 1 .. $how_many;
print "Your random numbers are: \n@numbers\n";
print "The mean of those numbers is: ", average(@numbers), "\n";
sub average{
my $total;
$total += $_ for @_;
return sprintf '%.2f', $total / @_;
}
Nice work, so far! It's almost ok. But you are calling your average function without
any parameters (&average
). Try it like so:
sub average{
my @Array_To_Average = @_; # this is now a local copy of the global @AllNumbers
my $total = 0;
for (@Array_To_Average) # iterate over the local copy ...
{
$total += $_; # ...and sum up
}
return $total / $random_number;
# instead of $random_number you could also use
# scalar(@Array_To_Average). That's the number of items
# in the array, i.e.
# return $total / scalar(@Array_To_Average);
}
print ("\n\nThe average of those random numbers is: ", average(@AllNumbers), "\n\n");
Please omit the &
when calling functions. That's very old style.
Prefer the style used in most other languages:
my $result1 = some_function();
my $result2 = some_other_function($param1, $param2);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With