c - 我编写这段代码是为了检查一个数字是质数、阿姆斯特朗数还是完美数,由于某种原因,当我使用大数时它不会打印

标签 c logic

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int CheckNumber(long long int x);
int prime(long long int n);
int armstrong(long long int z);
int perfect(long long int y);

int main()
{
    long long int i;
    long long int x;
    for (i = 1; i > 0; i++)
    {
        long long int n, s;
        printf("\nEnter a number to be checked:");
        scanf("%lld", &n);
        s = CheckNumber(n);
        switch (s)
        {
        case (0):
            printf("\nThis number is Prime");
            break;
        case (1):
            printf("\nThis number is Perfect");
            break;
        case (2):
            printf("\nThis number is Armstrong");
            break;
        case (3):
            printf("\nThis number is Armstrong & Prime");
            break;
        case (4):
            printf("\nThis number is Armstrong & Perfect.");
            break;
        case (5):
            printf("\nThis number is otherwise.");
            break;
        }
        printf("\n\nwant to check another number?\n(1) to continue (0) to close.");
        scanf("%lld", &x);
        if (x == 0)
        {
            break;
        };
    }
    return 0;
}

int prime(long long int n)
{
    long long i, check = 0;
    if (n == 0 || n == 1)
        check = 1;

    for (i = 2; i <= n / 2; ++i)
    {
        if (n % i == 0)
        {
            check = 1;
            break;
        }
    }
    if (check == 0)
    {
        return 0;
    }
    return 1;
}

int perfect(long long int y)
{
    long long int n, i = 1, np = 0;
    n = y;
    do
    {
        if (n % i == 0)
        {
            np = np + i;
        }
        i++;
    } while (i != n);
    if (np == n)
    {
        return 1;
    }
    return 2;
}

int armstrong(long long int z)
{
    long long int  nfi, i, host, sum = 0, y;
    y = z;
    if (z == 0)
    {
        return 2;
    }
    nfi = floor(log10(y) + 1);
    for (i = 1; i <= nfi; i++)
    {
        host = y % 10;
        sum += pow(host, nfi);
        y = y / 10;
    }
    if (z == sum)
    {
        return 2;
    }
    return 3;
}

int CheckNumber(long long int x)
{
    if (x == 0 || x == 1)
    {
        return 2;
    }
    if (prime(x) == 0)
    {
        if (armstrong(x) == 2)
        {
            return 3;
        }
        else
        {
            return 0;
        }
    }
    else if (perfect(x) == 1)
    {
        if (armstrong(x) == 2)
        {
            return 4;
        }
        else
        {
            return 1;
        }
    }
    else if (armstrong(x) == 2)
    {
        return 2;
    }
    else
    {
        return 5;
    }
}

这段代码有四个函数。

  • prime 函数检查一个数字是否为素数;当它是素数时返回 0,否则返回 1。

  • perfect 函数检查一个数字是否完美;如果完美则返回 1,否则返回 2。

  • armstrong 函数检查一个数字是否为 Armstrong;如果是阿姆斯特朗,则返回 2;如果不是,则返回 3。

  • checknumber 函数检查数字是否为素数、阿姆斯特朗数或完全数。它返回:

  • 如果数字是素数,则为 0。

  • 如果数字是完美的,则为 1。

  • 如果号码是阿姆斯特朗,则为 2。

  • 如果数字是阿姆斯特朗且素数,则为 3。

  • 如果数字是阿姆斯特朗且完美,则为 4。

  • 5 否则。

main函数中, 我做了一个无限循环来询问用户他想要检查的号码,检查后,我询问用户是否想要检查另一个号码。我还为 checknumber 函数创建了一个 switch 来打印输入的数字,例如:

用户输入7,输出为:

 This number is Armstrong & Prime.
 Want to check another number? (1) to continue; (0) to close.

问题是,当我使用这个数字(28116440335967)进行检查时,程序从未产生任何输出,我也不知道为什么。

最佳答案

您需要一种更有效的算法来检查素数和完全数:按照编码,您在 prime() 函数中迭代最多 n/2 次,并且nperfect() 函数。

由于 28116440335967 是质数,prime(x) 需要很长时间,而 perfect(x) 甚至更长,这解释了缺少输出:程序正在全速运行,但时间太长。

您可以通过仅迭代到 x 的平方根来降低这两个函数的复杂性:

int prime(long long int n) {
    if (n < 2)
        return 0;
    if (n % 2 == 0)
        return n == 2;
    for (long long i = 3; i <= n / i; i += 2) {
        if (n % i == 0) {
            return 1;
        }
    }
    return 0;
}

int perfect(long long int n) {
    long long int i, q, np = 1;

    for (i = 2; i <= (q = n / i); i++) {
        if (n % i == 0) {
            np = np + i;
            if (q != i)
                np = np + q;
        }
    }
    if (np == n) {
        return 1;
    } else {
        return 2;
    }
}

另请注意以下备注:

  • prime() 函数返回 0非常令人困惑的数字是质数而 1 否则。

  • prime()armstrong()perfect() 返回 会更加直观如果数字分别不是质数、阿姆斯特朗或完美数,则为 0;如果是,则为 1

  • CheckNumber() 返回值使用二进制指示符组合将使代码更简单且更具可读性。

  • 建议对 armstrong() 函数使用整数算术,以避免函数 log10pow 中出现精度问题。

这是修改后的版本:

#include <stdio.h>

enum { PRIME = 1, ARMSTRONG = 2, PERFECT = 4 };

int checkNumber(long long int x);
int prime(long long int n);
int armstrong(long long int n);
int perfect(long long int n);

int main(void) {
    for (;;) {
        long long int n;

        printf("Enter a number to be checked: ");
        if (scanf("%lld", &n) != 1) {
            printf("\n");
            break;
        }
        switch (checkNumber(n)) {
        case PRIME:
            printf("This number is Prime\n");
            break;
        case PERFECT:
            printf("This number is Perfect\n");
            break;
        case ARMSTRONG:
            printf("This number is Armstrong\n");
            break;
        case ARMSTRONG + PRIME:
            printf("This number is Armstrong & Prime\n");
            break;
        case ARMSTRONG + PERFECT:
            printf("This number is Armstrong & Perfect.\n");
            break;
        default:
            printf("This number is otherwise.\n");
            break;
        }
    }
    return 0;
}

int prime(long long int n) {
    if (n < 2)
        return 0;
    if (n % 2 == 0)
        return n == 2;
    for (long long i = 3; i <= n / i; i += 2) {
        if (n % i == 0) {
            return 0;
        }
    }
    return 1;
}

int perfect(long long int n) {
    long long int i, q, np = 1;

    for (i = 2; i <= (q = n / i); i++) {
        if (n % i == 0) {
            np = np + i;
            if (q != i)
                np = np + q;
        }
    }
    return np == n;
}

int armstrong(long long int n) {
    long long int sum;
    long long int x;
    int nfi;

    if (n == 0)
        return 0;
    for (nfi = 0, x = n; x; x /= 10)
        nfi++;
    for (sum = 0, x = n; x; x /= 10) {
        long long int digit = x % 10;
        long long int val = digit;
        for (int i = 1; i < nfi; i++) {
            val *= digit;
        }
        sum += val;
    }
    return (n == sum);
}

int checkNumber(long long int n) {
    return prime(n) * PRIME | perfect(n) * PERFECT | armstrong(n) * ARMSTRONG;
}

关于c - 我编写这段代码是为了检查一个数字是质数、阿姆斯特朗数还是完美数,由于某种原因,当我使用大数时它不会打印,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77340316/

相关文章:

c - 计算参数数量的宏

c - 错误 : Couldn't open stream with SDL 1. 3

c - C中的String Inverter Program中的警告

c# - 产品配置器难以依存地管理数据/项目

c++ - 稀疏建模软件编译错误

mysql - 计算元件更换次数

java - 为什么这个 while 循环会导致无限循环?

ios - 有趣的重叠 UIScrollView 难题

c# - 如何停止传送门 A 和 B 之间的无限旅行?

在 C 中将字母转换为数字