Perl 从随机填充的数组中计算平均值



我有一个学校作业需要帮助。现在,我知道你在想什么,但我的老师不在城里,没有回复我的电子邮件,我的其他同学也不知道如何解决这个问题。一些指示和提示将不胜感激!

作业是这样的:

我们应该创建一个数组,用 1-100 范围内的 20 到 30 个随机整数填充它。然后,借助子例程,我们应该计算这些数字的平均值。

当我回调子例程时出现问题,它给了我答案 0 或"非法除以 0"错误。我现在的代码是这样的:

#! /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( "nnThe average of those random numbers is: ", &average, "nn" );

现在,正如我所说,我想自己解决这个问题,我已经花了整整两天的时间,但似乎无论我做什么都无法解决它。任何提示将不胜感激。附言应该提到的是,我们不应该使用任何模块/插件。

我首先要解决几个风格点:

  • 把你的潜艇放在开头(或者如果你必须的话,放在最后(。把它放在代码中间是混乱的。

  • 不要用&调用子例程 - 这是糟糕的风格,并且会导致一些奇怪的行为。在您的情况下:&average实际上是在没有参数的情况下被调用的。不过,一般来说这很糟糕,除非您明确知道为什么要这样做,否则不要使用它。(它确实有一些用途,但当你看到它们时你会知道 - 而且你在早期学习perl时不会(。

  • 像这样的数组大写不是好的形式,因为这就是模块/包的命名方式。如果可以的话,坚持使用小写变量。

  • 你的 for 循环是一种 C 风格,它有效,但最好写for ( 1..$random_number ) {因为你不需要迭代器。

  • 你不需要-w在社邦线上,因为你有use warnings. use warnings;是更好的方法。

  • 调用变量$random_number不是很有帮助 - 我们可以看到这一点,因为它为 rand 分配了结果。称它为它的用途 - 就像$number_of_elements.

  • 鉴于您只需要使用一次$random_number,您可能不需要将其粘贴在变量中。如果你觉得它有助于可读性,你可以(这是一个品味问题 - 在好的编程中,清晰和可读是唯一真正重要的事情 - 考虑到当今编译器的状态,大多数内存/性能都是过早的优化。

不过,你在这里的核心问题是:

my $ArrayAverage = @_;

这会$ArrayAverage列表中元素的数量。这将始终与 $random_number 相同,因为这是您迭代的次数。

您在此处迭代元素,但实际上并不使用 $total

for (@_) {
    my $total += $_;
}

所以在这里 - 你返回数组中的元素数除以数组中的元素数。

return $ArrayAverage / $random_number;

但真正重要的是 - 这些都不重要,因为你用&average调用它,而实际上并没有发送任何参数。所以你只是输入零,然后得到零。

知道这一点可能很有用 - 标量上下文中的数组返回元素的数量,因此计算平均值就像:

my $sum; 
$sum += $_ for @AllNumbers; 
print( "nnThe average of those random numbers is: ", $sum / @AllNumbers, "nn" );

这将生成一个长小数 - 如果您需要格式化它,您可以使用 printfsprintf .

printf( "nnThe average of those random numbers is: %02.2f nn", $sum / @AllNumbers);

所以我会稍微重写一下:

#!/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_numbersn");
#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( "nnThe average of those random numbers is: %02.2f nn", $sum / @all_numbers);

用惯用的Perl写它会给你这样的结果:

#!/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@numbersn";
print "The mean of those numbers is: ", average(@numbers), "n";
sub average{
  my $total;
  $total += $_ for @_;
  return sprintf '%.2f', $total / @_;
}

到目前为止,干得不错!差不多没问题。但是你正在调用你的平均函数,没有任何参数 ( &average (。像这样尝试:

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 ("nnThe average of those random numbers is: ", average(@AllNumbers), "nn");

调用函数时请省略&。这是非常古老的风格。首选大多数其他语言中使用的样式:

my $result1 = some_function();
my $result2 = some_other_function($param1, $param2);

干得好,你在寻求帮助之前尝试过自己工作!

若要调试代码,请尝试添加一些打印,以最大程度地减少需要查找错误的区域。因此,在这种情况下,您可以在平均 sub 中添加print $random_number,您会注意到它设置正确。而如果你打印$ArrayAverage的元素,你会发现它没有值,这仅仅是因为你需要在脚本最后一行的打印中调用它时将@AllNumbers数组传递给 &average sub。

所以解决方案是你只需要在被调用时将@AllNumbers数组传递给 &average((:

print ("nnThe average of those random numbers is: ", &average(@AllNumbers), "nn");

这应该可以正常工作;)祝你好运!

(主要(问题是你调用你的 sub 没有参数!试试这个:

average($_) foreach @AllNumbers;
my $count = 0;
my $total;
my $average;
sub average{
    my $num = shift;
    $count++; # count number of random numbers 
    $total += $num; # sum up
    $average = $total/$count; # calculate average
    return $average;
}
# Print the mean/average of the 20-30 numbers.
print ("nnThe average of those random numbers is: ", $average, "nn");

让它来帮助你。

#! /usr/bin/perl -w
use warnings;
use strict;
# Declaring the scalar variables and arrays.
my @AllNumbers;
my $avgOfArray;
# 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 @array = @_; # save the array passed to this function
    my $sum; # create a variable to hold the sum of the array's values
    foreach (@array) { $sum += $_; } # add each element of the array
    # to the sum
    return $sum/@array; # divide sum by the number of elements in the
    # array to find the mean
}
$avgOfArray = average(@AllNumbers);
# Print the mean/average of the 20-30 numbers.
print ("nnThe average of those random numbers is: ",  $avgOfArray,     "nn"); here
您需要

将参数传递给average子例程:

#!/usr/bin/perl
sub average{
  my $tot;
  $tot += $_ for @_;
  return sprintf '%.3f', $tot / @_;
}
my @num;
my $quantity = int(rand 11) + 20;    
push @num, int(rand 100) + 1 for 1 .. $quantity;
print "Random numbers: t@numn";
print "Average: ", average(@num), "n";