在Perl中创建一个阶乘子例程

时间:2015-02-20 23:46:17

标签: perl subroutine factorial

我是第一次发布海报和新程序员。

我正在尝试创建一个程序,该程序将采用不到一千的3和5的倍数,然后将它们加在一起作为最终总和。

我正在练习子程序,因此我尝试使用单个子程序,我只需要3或5就可以。

我觉得我很接近,但它会不断返回无穷无尽的零,所以我必须在脚本中输入Ctrl-C。

我遇到的另一个问题是阵列接收1000(在5的情况下)和1002(在3的情况下)。如何将数字1000或更高的数字停在数组中?

我想开始练习递归。递归会更适合解决这个问题吗?

这是我的代码:

#!/usr/bin/perl -w

use strict;

sub multiples;


my $sum_threes = multiples(3);
my $sum_fives = multiples(5);

my $total_sum = $sum_threes + $sum_fives;
print $total_sum, "\n";


sub multiples {
    my $input_number;
    my $sum_number = 0;
    my $count_number = 0;
    my @count_array;

    while ($count_number < (1000 - $input_number)) {
        $count_number += $input_number;
        push(@count_array, $count_number);
        print "$_\n" for @count_array;
    }
    foreach (@count_array) {
        $sum_number += $_;
    }
    print "Total sum of factorial for multiples of $input_number is $sum_number.\n";
    return $sum_number;
}

3 个答案:

答案 0 :(得分:4)

编程是关于在编程语言中实现algorithm。您应该专注于语言为您提供的工具和设施,而不是您尝试实现的算法。

您在Perl代码中犯了一个相当微不足道的错误:变量$input_number永远不会赋值。 Perl子例程接收在内置数组@_中传递给它的参数,并且可以通过编写

$input_number设置为传入的第一个值
my $input_number = shift;

如果您只是进行了更改,那么您将看到您的程序做某事。但它没有做的是计算因子,因为你的算法是错误的。毕竟,3的阶乘是3×2×1 = 6,并且与1000的值没有任何关系。

我会帮你解决这个问题,但是你的目标对于第一个程序来说太高了。目前,这里有一些基于您的代码的建议,可以帮助您了解森林。

  • 为变量使用长而有意义的名称似乎很有帮助。但实际上,如果名称太长,那么它们就会隐藏程序的结构。将您的标识符保持在十个字符以下

  • 除了简洁之外,变量名称应该有意义。您的$count_number@count_array与计数无关:$count_number是通过添加$input_number的连续倍数计算得出的值,而@count_array是这些值的列表值

  • 出于同样的原因,请使用for代替foreach。它们是相同的

  • 编写子程序以根据其参数执行中间操作。将其留给调用者来决定如何处理结果。特别是,除非用于调试目的,否则子例程通常不应具有print语句

以下是我将如何编写您发布的代码。它仍然不起作用,但我希望你能看到它比原版更具可读性。 实际上所做的是计算1000 2 的奇异分数,但为了解决这个问题,你需要修复算法

我希望你能看到缩进的价值,以及更短但仍然有意义的变量名吗?

#!/usr/bin/perl

use strict;
use warnings;

my $sum_threes = multiples(3);
print "Total sum of factorial for multiples of 3 is $sum_threes.\n";

my $sum_fives  = multiples(5);
print "Total sum of factorial for multiples of 3 is $sum_fives.\n";

my $total_sum = $sum_threes + $sum_fives;
print $total_sum, "\n";

sub multiples {

    my $number = shift;

    my @values;

    my $value = $number;
    while ( $value < 1000 ) {
        push @values, $value;
        $value += $number;
    }

    my $sum = 0;
    $sum += $_ for @values;

    return $sum;
}

答案 1 :(得分:1)

顶级答案:你太过分了。学习编写一个从1到10的简单循环并打印出值;学会编写一个接收参数的简单子程序,并将其用于微不足道的事情;学会编写一个简单的程序,它从数组中获取值并将它们加在一起。

这与factorial有什么关系?!

具体说明:

  1. 你的缩进是关闭的。没有正确的缩进,代码几乎不可能被读取。我不得不六次看它才能理解它。
  2. &#34;没有缩进的计算&#34;

    1. 你的循环逻辑缺少一个关键因素:&#34;进展&#34;或者&#34;增量&#34;步。 $ count_number和$ input_number都不会在循环体内发生变化,因此循环顶部的条件永远不会改变真值。

    2. 还有其他一些逻辑问题,例如在添加它之前,实际上并没有区分$ count_number是否实际上是多个。

    3. 您应该为参数命名,例如:

      my $mult_value = shift;
      
    4. 位于子程序的顶部。

      1. Re:递归:不。当然可以。但教学上:拿。它。慢。
      2. 祝你好运!

答案 2 :(得分:1)

这不是一个真正的答案,而是&#34; factorial&#34;让我想起马克杰森多米努斯Higher Order Perl这是一本很好的书(如果你仍然可以找到它,推荐)。它直接写入简单而强大的功能开始让你在第2页开始思考,直到第500页继续前进。这是他从第5页开始的阶乘子程序:

sub factorial {
  my ($n) = @_;
  return 1 if $n == 0;
  return factorial($n-1) * $n;
}
当我想要超越&#34;程序perl&#34;时,HOP是一个充满想法的宝库。当你花费时间用perl版本替换shell脚本时,这就成了习惯。感谢MJD。