0

如何使用for循环或while循环编写逻辑以打印Armstrong 数字

有人请解释如何打印 1 到 1,00,00,000 之间的 Armstrong 数字。

这是我遵循的算法

step 1 : initializing variable min,max,n,sum,r,t
step 2 : my $n = <>;
step 3 : to find base of $n
step 4 : using for loop 
        ( for (n = min; n < max ; n++ )
step 5 : some logic like 
        n=t,sum =0,r=t%10,t=n/10,
step 6 : 
        sum = sum + (n ^ base );
step 6 : 
        if ( sum == num ) print Armstrong numbers else not.

我试图编码这个我的代码看起来像这样

#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;

my $n;
chomp($n);

my $min = 1;
my $max = 10000000
my $r;
my $sum;
my $t;

my $base = length($n);
print "base is $base\n";

for ($n = $min; $n <= $max; $n++) {
  $t = $n;
  $sum = 0;
  while ($t != 0) {
    $r = $t % 10;
    $t = $t / 10;
    {
      $sum = $sum + ($base * $r);
    }
    if ($sum == $n) {
      print "$n\n";
    }
  }
}
4

3 回答 3

1

几件事:

  • my在需要之前声明某些东西是不好的做法。
  • 您必须记住,数字也是字符串,可以通过字符串函数(如split.
  • 在 Perl 中不鼓励使用类 C 循环,因为它们难以阅读。
  • 常量应该是……嗯……常量

这是我的尝试。我split用来将我的数字拆分成一个数字数组。这比不断除以十要容易得多。@digits我可以通过简单地获取数组的标量值来获得位数。

然后我可以循环遍历@digits,将每一个都$power添加到sum. 我使用map这个循环的命令,但我也可以使用另一个for循环。

#! /usr/bin/env perl
#
use strict;
use warnings;
use feature qw(say);

use constant {
    MIN             => 1,
    MAX             => 1_000_000,
};

for my $number ( (+MIN..+MAX) ) {
    my @digits = split //, $number;
    my $power = @digits;
    my $sum = 0;
    map { $sum += $_**$power } @digits;
    if ( $sum == $number ) {
        say "$number is an Armstrong number";
    }
}

我的输出:

1 is an Armstrong number
2 is an Armstrong number
3 is an Armstrong number
4 is an Armstrong number
5 is an Armstrong number
6 is an Armstrong number
7 is an Armstrong number
8 is an Armstrong number
9 is an Armstrong number
153 is an Armstrong number
370 is an Armstrong number
371 is an Armstrong number
407 is an Armstrong number
1634 is an Armstrong number
8208 is an Armstrong number
9474 is an Armstrong number
54748 is an Armstrong number
92727 is an Armstrong number
93084 is an Armstrong number
548834 is an Armstrong number

跑了五秒钟多一点。

而不是map,我可以做这个循环:

for my $digit ( @digits ) {
    $sum = $sum + ( $digit ** $power);
}
于 2013-08-07T19:13:46.233 回答
0

您的代码似乎是正确的,但是您在开始时遇到了一些问题。例如,您不读取STDIN或读取自@ARGV. 你会这样做吗,你在计算指数计算时遇到了一个小问题。在大多数编程语言中,指数计算的语法是**pow()函数。我真的不明白,这部分是什么:

while ($t != 0) {
    $r = $t % 10;
    $t = $t / 10;
    {
      $sum = $sum + ($base * $r);
    }
    if ($sum == $n) {
      print "$n\n";
    }
}

什么是裸块?为什么要使用模数?.. 好吧,我给你一个小代码,用于计算基数为1..1000 到 1000 万之间的阿姆斯壮数:

#!/usr/bin/perl
use strict;
use warnings;
foreach my $base (0..100) {               # use the foreach loop as base
  for my $num (0..10_000_000) {           # and use numbers between this range
    my $ce=0;                             # ce = calculated exp.
    foreach my $num2 (split //,$num ) {   # split each number for calc each
      $ce += $num2 ** $base;              # exp. and adding it (see algorithm)
    }
    if ($num == $ce) {                    # when the exp. num and the number
      print "$base => $num\n";            # itself equals, its a armstrong number
    }                                     # print that
  }
}
于 2013-08-07T17:44:52.920 回答
0

这个是在大学...

我挖出了我用 C 制作的那个,并为你将它转换为 perl(这可能不是最好的方法,但我就是这样做的):

#!/usr/bin/env perl

use strict;
use warnings;

my $min = 1;
my $max = 10000000;

for (my $number = $min; $number <= $max; $number++) {
    my @digits = split('', $number);
    my $sum = 0;
    foreach my $digit (@digits) {
        $sum += $digit**length($number);
    }
    if ($sum == $number) {
        print "$number\n";
    }
}

Demo - 1 到 9999 由于执行时间限制

于 2013-08-07T11:38:15.600 回答