找到3中最大的数字

时间:2017-01-02 18:26:02

标签: perl

我试图编写一个脚本来查找3个数字中最大的数字,并通过命令行参数传递它们

我只是想知道我在这段代码中写的错误是什么,感谢您的帮助。

:::

4 个答案:

答案 0 :(得分:10)

您的maximum功能存在缺陷:

  • 如果第一个数字大于第二个数字,则只尝试第三个数字。
  • 您没有正确检索参数; $num1$num2都获得第一个,$num3从未设置。
  • 您永远不会返回$max值。
  • 您不打印结果。
  • 您不会调整变量的范围。
  • 没有理由chomp参数。

以下是一些代码,它们有五种不同的函数参数检索方法:

sub max1 {
    my $num1 = $_[0];
    my $num2 = $_[1];
    my $num3 = $_[2];
    my $max = $num1;
    $max = $num2 if $num2 > $max;
    $max = $num3 if $num3 > $max;
    return $max;
}

sub max2 {
    my $num1 = shift;
    my $num2 = shift;
    my $num3 = shift;
    my $max = $num1;
    $max = $num2 if $num2 > $max;
    $max = $num3 if $num3 > $max;
    return $max;
}

sub max3 {
    my ($num1, $num2, $num3) = @_;
    my $max = $num1;
    $max = $num2 if $num2 > $max;
    $max = $num3 if $num3 > $max;
    return $max;
}

# Works for any number of arguments.
sub max4 {
    my $max = shift;
    foreach my $foo (@_) {
        $max = $foo if $max < $foo;
    }
    return $max;
}

# Works for any number of arguments.
use List::Util qw( max );

my $n1 = $ARGV[0];
my $n2 = $ARGV[1];
my $n3 = $ARGV[2];

printf "%d\n", max1($n1, $n2, $n3);
printf "%d\n", max2($n1, $n2, $n3);
printf "%d\n", max3($n1, $n2, $n3);
printf "%d\n", max4($n1, $n2, $n3);
printf "%d\n", max($n1, $n2, $n3);

# Even simpler:
printf "%d\n", max1 @ARGV;
printf "%d\n", max2 @ARGV;
printf "%d\n", max3 @ARGV;
printf "%d\n", max4 @ARGV;
printf "%d\n", max @ARGV;

答案 1 :(得分:8)

原始代码中的逻辑错误是有时候第三个数字永远不会被测试。 elsif应为if

您也依赖于隐含的返回值,这会让您感到惊讶。例如,如果您要进入elsif条件,并且其条件表达式为false,则maximum函数将返回false值(空字符串),这根本不是什么你真的想要。这是因为如果Perl在子例程中没有命中return语句,它将返回最后一个表达式的值。在这种情况下,最后一个表达式可以是条件评估。另一个令人惊讶的事情是它可以在条件求值为true的情况下工作,因为在这种情况下,最后一个表达式被分配给$max,所以这就是返回的内容。

更通用的解决方案将采用任意数量的数字并找到最大值。事实证明,通过使用循环,我们可以消除链式if(){...} elsif()...语句,同时变得更加灵活。这是一个合理的通用方法,适用于任何大小的数字列表:

sub maximum {
    my $max = shift;
    foreach my $num (@_) {
        $max = $num if $num > $max;
    }
    return $max;
}

print maximum(1,5,3), "\n"; # Prints 5.

但是还有更好的方法:

use List::Util 'max';

print max(1,5,3), "\n"; # Also prints 5.

List::Util模块附带Perl,因此您不必安装任何您不应该拥有的模块。

答案 2 :(得分:3)

除了chqrlie's answer之外,我还想向您介绍Perl Modules,让您轻松完成工作。例如,在您的情况下,您可以使用List::Util模块。它是一个核心模块,因此您不必付出额外的努力来安装它。

示例:

#!/usr/bin/perl
use strict;
use warnings;
use List::Util qw( max );
my $maximum = max @ARGV;
print "Maximum: $maximum\n";

Demo

答案 3 :(得分:3)

你确实应该使用List::Util::max。但是,仅仅为了多样化,这里有一个获得最多三个参数的简洁方法:

sub max_of_3 {
    my $x = $_[ $_[1] > $_[0] ];
    return $_[2] > $x ? $_[2] : $x;
}

以下是一些测试代码以及​​基准测试:

#!/usr/bin/env perl

use strict;
use warnings;

use Algorithm::Combinatorics qw( permutations );
use Dumbbench;
use List::Util qw( max );
use Test::More;

sub dummy { }

sub max_of_3 {
    my $x = $_[ $_[1] > $_[0] ];
    return $_[2] > $x ? $_[2] : $x;
}

sub classic {
    my $num1 = $_[0];
    my $num2 = $_[1];
    my $num3 = $_[2];
    my $max = $num1;
    $max = $num2 if ($num2 > $max);
    $max = $num3 if ($num3 > $max);
    return $max;
}

for my $case ( permutations([5, 6, 7])) {
    is max_of_3(@$case), 7, "max of [@$case] is 7";
}

done_testing;

my $bench = Dumbbench->new;

$bench->add_instances(
    Dumbbench::Instance::PerlSub->new(
        name => 'Dummy',
        code => sub { dummy(5, 6, 7) },
    ),
    Dumbbench::Instance::PerlSub->new(
        name => 'compact',
        code => sub { max_of_3(5, 6, 7) },
    ),
    Dumbbench::Instance::PerlSub->new(
        name => 'List::Util::max',
        code => sub { max(5, 6, 7) },
    ),
    Dumbbench::Instance::PerlSub->new(
        name => 'classic',
        code => sub { classic(5, 6, 7) },
    ),
);

$bench->run;
$bench->report;

基准输出:

Dummy: Ran 21 iterations (0 outliers).
Dummy: Rounded run time per iteration: 1.4729e-007 +/- 4.1e-010 (0.3%)
compact: Ran 27 iterations (7 outliers).
compact: Rounded run time per iteration: 3.8513e-007 +/- 8.4e-010 (0.2%)
List::Util::max: Ran 37 iterations (8 outliers).
List::Util::max: Rounded run time per iteration: 1.28262e-007 +/- 2.3e-011 (0.0%)
classic: Ran 27 iterations (7 outliers).
classic: Rounded run time per iteration: 5.81187e-007 +/- 9.2e-011 (0.0%)

故事的道德:1)使用完善的图书馆,而不是自己动手。这里List::Util::max比调用一个什么都不做的子程序要快,因为它是在XS中实现的; 2)除非你能提出一个非常非常好的理由,否则更喜欢清晰度而不是紧凑性。在大多数情况下,即使速度提高35%也是不值得的,特别是因为使用List::Util::max同时更清晰,更紧凑它的性能优于两种手动选择。您也不必编写新代码来处理 N 参数。