应该打印高达 999 的阿姆斯特朗数字的代码有什么问题



这是用C语言编写的代码,它应该打印给定范围1-999内的Armstrong数。但代码既没有打印任何内容,也没有使用CPU资源。很可能它在一个无休止的循环中得到了结构。这是代码-

//C program to print Armstrong numbers up to 999
#include <math.h>
#include <stdio.h>
int main()
{
int i = 1, b, sum = 0;
printf("The Armstrong Numbers Within 0-999 are --> ");
while (i <= 999)
{
while (i != 0)
{
b = i % 10;
i = i / 10;
sum = sum + pow(b, 3);
}
if (i == sum)
{
printf("%d ", i);
sum = 0;
}
else
{
sum = 0;
}
i++;
}
return 0;
}

应在不添加任何其他附加库函数的情况下回答。

代码有问题。。。

内部while循环破坏了i的[原始]值,因此后续的if将失败,因为i始终为零。内部循环应该使用一个临时变量。

无需使用pow,因为b * b * b更好/更快,[可能]更准确。使用pow似乎违反了标准:

需要在不添加任何其他附加库函数的情况下进行回答。

ifelse中的sum = 0;都是冗余的。它可以移到下面。但是,最好把它放在外循环的开头。

你的第一个printf说范围是0-999,但你在1 开始你的外循环

该算法使用每个多维数据集的总和:https://www.javatpoint.com/armstrong-number-in-c

然而,维基百科https://en.wikipedia.org/wiki/Narcissistic_number声明我们应该将数字相加为数字中数字的幂(例如pow(b,ndig)(。

";立方体";该算法对4位数的数字不起作用。


这里有一个重构的版本,它对多维数据集进行求和:

//C programme to print Armstrong numbers up to 999
#include <stdio.h>
int
main(void)
{
int lo = 0;
int hi = 999;
printf("The Armstrong Numbers Within %d-%d are --> ",lo,hi);
for (int i = lo;  i <= hi;  ++i) {
int sum = 0;
for (int j = i;  j != 0;  j /= 10) {
int b = j % 10;
sum += b * b * b;
}
if (i == sum)
printf("%d ", i);
}
printf("n");
return 0;
}

这是程序输出:

The Armstrong Numbers Within 0-999 are --> 0 1 153 370 371 407

这里有一个使用维基百科定义的版本:

//C programme to print Armstrong numbers up to 999
#include <stdio.h>
#ifdef DEBUG
#define dbgprt(_fmt...)     printf(_fmt)
#else
#define dbgprt(_fmt...)     do { } while (0)
#endif
// xpow -- raise to a power
int
xpow(int base,int exp)
{
int ret = 1;
dbgprt("xpow: ENTER base=%d exp=%dn",base,exp);
while (1) {
dbgprt("xpow: LOOP base=%d exp=%8.8Xn",base,exp);
if (exp & 1)
ret *= base;
exp >>= 1;
if (exp == 0)
break;
base *= base;
}
dbgprt("xpow: EXIT ret=%dn",ret);
return ret;
}
int
armstrong(int ndig,int i)
{
if (ndig == 0) {
ndig = i ? 0 : 1;
for (int j = i;  j != 0;  j /= 10, ++ndig);
}
int sum = 0;
for (int j = i;  j != 0;  j /= 10) {
int b = j % 10;
b = xpow(b,ndig);
sum += b;
}
int match = (i == sum);
dbgprt("armstrong: MATCH match=%d i=%dn",match,i);
return match;
}
void
armndig(int ndig)
{
dbgprt("armndig: ENTER ndig=%dn",ndig);
int lo = xpow(10,ndig - 1);
if (lo == 1)
lo = 0;
int hi = xpow(10,ndig) - 1;
printf("The Armstrong Numbers Within %d-%d are -->n",lo,hi);
for (int i = lo;  i <= hi;  ++i) {
if (armstrong(ndig,i))
printf("ARMSTRONG %dn",i);
}
dbgprt("armndig: EXITn");
}
int
main(void)
{
armstrong(3,407);
for (int ndig = 1;  ndig <= 4;  ++ndig)
armndig(ndig);
return 0;
}

这是程序输出:

The Armstrong Numbers Within 0-9 are -->
ARMSTRONG 0
ARMSTRONG 1
ARMSTRONG 2
ARMSTRONG 3
ARMSTRONG 4
ARMSTRONG 5
ARMSTRONG 6
ARMSTRONG 7
ARMSTRONG 8
ARMSTRONG 9
The Armstrong Numbers Within 10-99 are -->
The Armstrong Numbers Within 100-999 are -->
ARMSTRONG 153
ARMSTRONG 370
ARMSTRONG 371
ARMSTRONG 407
The Armstrong Numbers Within 1000-9999 are -->
ARMSTRONG 1634
ARMSTRONG 8208
ARMSTRONG 9474

更新:

int xpow(int base,int exp)未准备好用于一般用途,因为当exp < 0时,它有一个无限循环。如果代码使用x%2而不是x&1,使用exp /= 2;而不是exp >>= 1;,就像上面使用%10和/10(或unsigned exp(的代码一样,那么这个无限循环就不存在了chux-恢复Monica

你是对的。我从一个已经使用了unsigned参数的函数中改编了代码。

我一直在争论是否要全程使用unsigned和使用unsigned long long

这是一个进一步清理的版本:

//C programme to print Armstrong numbers up to 999
#include <stdio.h>
#if USE64
typedef unsigned long long num_t;
#define FMT                 "%llu"
#define FMTX                "%16.16X"
#define NDIG                16
#else
typedef unsigned int num_t;
#define FMT                 "%u"
#define FMTX                "%8.8X"
#define NDIG                8
#endif
#ifdef DEBUG
#define dbgprt(_fmt...)     printf(_fmt)
#else
#define dbgprt(_fmt...)     do { } while (0)
#endif
// xpow -- raise to a power
num_t
xpow(num_t base,num_t exp)
{
num_t ret = 1;
dbgprt("xpow: ENTER base=" FMT " exp=" FMT "n",base,exp);
while (1) {
dbgprt("xpow: LOOP base=" FMT " exp=" FMTX "n",base,exp);
#if CHUX
if (exp % 2)
ret *= base;
exp /= 2;
#else
if (exp & 1)
ret *= base;
exp >>= 1;
#endif
if (exp == 0)
break;
base *= base;
}
dbgprt("xpow: EXIT ret=" FMT "n",ret);
return ret;
}
num_t
armstrong(int ndig,num_t i)
{
if (ndig == 0) {
ndig = i ? 0 : 1;
for (num_t j = i;  j != 0;  j /= 10, ++ndig);
}
num_t sum = 0;
for (num_t j = i;  j != 0;  j /= 10) {
num_t b = j % 10;
b = xpow(b,ndig);
sum += b;
}
int match = (i == sum);
dbgprt("armstrong: MATCH match=%d i=" FMT "n",match,i);
return match;
}
void
armndig(int ndig)
{
dbgprt("armndig: ENTER ndig=%dn",ndig);
num_t lo = xpow(10,ndig - 1);
if (lo == 1)
lo = 0;
num_t hi = xpow(10,ndig) - 1;
printf("The Armstrong Numbers Within " FMT "-" FMT " are -->n",lo,hi);
for (num_t i = lo;  i <= hi;  ++i) {
if (armstrong(ndig,i))
printf("ARMSTRONG " FMT "n",i);
}
dbgprt("armndig: EXITn");
}
int
main(void)
{
setlinebuf(stdout);
armstrong(3,407);
for (int ndig = 1;  ndig <= NDIG;  ++ndig)
armndig(ndig);
return 0;
}

以下是-DUSE64=0:的程序输出

The Armstrong Numbers Within 0-9 are -->
ARMSTRONG 0
ARMSTRONG 1
ARMSTRONG 2
ARMSTRONG 3
ARMSTRONG 4
ARMSTRONG 5
ARMSTRONG 6
ARMSTRONG 7
ARMSTRONG 8
ARMSTRONG 9
The Armstrong Numbers Within 10-99 are -->
The Armstrong Numbers Within 100-999 are -->
ARMSTRONG 153
ARMSTRONG 370
ARMSTRONG 371
ARMSTRONG 407
The Armstrong Numbers Within 1000-9999 are -->
ARMSTRONG 1634
ARMSTRONG 8208
ARMSTRONG 9474
The Armstrong Numbers Within 10000-99999 are -->
ARMSTRONG 54748
ARMSTRONG 92727
ARMSTRONG 93084
The Armstrong Numbers Within 100000-999999 are -->
ARMSTRONG 548834
The Armstrong Numbers Within 1000000-9999999 are -->
ARMSTRONG 1741725
ARMSTRONG 4210818
ARMSTRONG 9800817
ARMSTRONG 9926315
The Armstrong Numbers Within 10000000-99999999 are -->
ARMSTRONG 24678050
ARMSTRONG 24678051
ARMSTRONG 88593477

最新更新