【问题标题】:How to print 10 perfect numbers from a user given number in C?如何从 C 中的用户给定数字打印 10 个完美数字?
【发布时间】:2020-02-27 07:04:23
【问题描述】:

我不知道如何打印下十个Perfect numbers。 到目前为止,这是我所得到的:

#include <stdio.h>

int main() {
    int n, c = 1, d = 2, sum = 1;
    printf("Enter any number \n");
    scanf("%d", &n);
    printf("The perfect numbers are:");
    while(c <= 10) { 
        sum = 1;
        d = 2;
        while(d <= n / 2) { //perfect no
            if(n % d == 0) {
                sum = sum + d;
            }
            d++;
        }
        if(sum == n) {
            printf("%d\n", n);
        }
        c++;
    }
    return 0;
}

我目前收到的输出:

input: 2 (say)  
output: 6  

我想要什么:

input: 2  
output:
6  
28  
496  
8128  
33550336  
858986905  
137438691328  
2305843008139952128  
2658455991569831744654692615953842176
191561942608236107294793378084303638130997321548169216

我刚刚开始编码。任何帮助将不胜感激。

【问题讨论】:

  • 请包括你当前程序的输出和你想要达到的输出。
  • 我有。请检查。
  • 在第六个条目(858986905 — 9 位)之后会出现(32 位)整数溢出。即使使用 64 位整数(unsigned long longuint64_t)也无法处理第八个整数(2305843008139952128 和 21 位)。因此,如果您对此很认真,则需要使用多精度(整数)算术包——其中有很多。
  • OEIS A000396 - 6,28,496,8128,33550336,8589869056,137438691328,2305843008139952128,2658455991569831744654692615953842176,191561942608236107294793378084303638130997321548169216 跨度>。
  • 注:191561942608236107294793378084303638130997321548169216 约为 178 位。

标签: c perfect-numbers


【解决方案1】:

你必须在找到一个完美数后放置计数器,因此增加c 必须发生在检查完美数的if 语句中,如下所示:

if(sum==n){
    printf("%d",n);
    c++;
}

在这之后你需要增加数字,称为n,像这样:

n++;

根据数字,@Jonathan Leffler 是对的,您应该使用适当的变量。

【讨论】:

    【解决方案2】:

    从你写的输出我相信你想展示 10 个第一个完美数字 现在你只显示 6,因为你显示它们从 1 到 10。在这个范围内只有 6。 我是这样写的:

    #include <stdio.h>
    int isperfect(int input) {
    int sum = 0, value = input / 2;
    do {
        if (input % value == 0) sum += value;
        value--;
    } while (value);
    if (input == sum) return 1;
    else return 0;
    }
    int main() {
    int i;
    int count;
    for (i = 2, count = 0; count < 4; i++) {
        if (isperfect(i) == 1) {
            count++;
            printf("%d\n", i);
        }
    }
    return 0;
    }
    

    但我不建议数超过 4,因为它会花费太多时间

    【讨论】:

      【解决方案3】:

      几个人提到的整数溢出问题很重要,但次要。即使我们修复了您损坏的逻辑,并对其进行调整以处理更大、固定大小的整数:

      #include <stdio.h>
      
      int main() {
          unsigned long long number;
          printf("Enter any number \n");
          scanf("%llu", &number);
          printf("The perfect numbers are:\n");
      
          int total = 0;
      
          while (total < 10) { 
              unsigned long long sum = 1, divisor = 2;
      
              while (divisor <= number / 2) {
                  if (number % divisor == 0) {
                      sum += divisor;
                  }
                  divisor++;
              }
      
              if (sum == number) {
                  printf("%llu\n", number);
                  total++;
              }
      
              number += 1;
          }
      
          return 0;
      }
      

      您仍然无法在任何合理的时间内超过前四个完美数字:

      > ./a.out
      Enter any number 
      2
      The perfect numbers are:
      6
      28
      496
      8128
      

      主要问题是您使用了错误的算法。阅读Mersenne primes,以及它们与完美数的关系,以及Lucas-Lehmer test。这种方法需要更多的思考,但令人惊讶的是,没有更多的代码。并且会更快地产生更多结果(尽管最终也会陷入困境。)

      【讨论】:

        【解决方案4】:

        Research,分而治之

        完全数的形式为 2p − 1 * (2p − 1)。

        代码需要扩展精度才能形成191561942608236107294793378084303638130997321548169216

        提高效率

        迭代到&lt;= n / 2 花费的时间太长了。迭代到&lt;= n / d

        // while(d <= n / 2) {
        while(d <= n / d) {
        

        改进代码示例:

        bool isprime(unsigned long long x) {
          if (x > 3) {
            if (x % 2 == 0) {
              return false;
            }
            for (unsigned long t = 3; t <= x / t; t += 2) {
              if (x % t == 0) {
                return false;
              }
            }
            return true;
          }
          return x >= 2;
        }
        

        高级:请参阅Lucas–Lehmer primality test 了解梅森数的快速素数检验


        以下代码适用于除第 10 个完美数之外的所有数字,因为代码必须测试 isprime(267 - 1),我应该为 OP 留下一些事情。

        static void buff_mul(char *buff, unsigned power_of_2) {
          unsigned long long m = 1ull << power_of_2;
          size_t len = strlen(buff);
          unsigned long long carry = 0;
          for (size_t i = len; i > 0;) {
            i--;
            unsigned long long sum = (buff[i] - '0') * m + carry;
            buff[i] = sum % 10 + '0';
            carry = sum / 10;
          }
          while (carry) {
            memmove(buff + 1, buff, ++len);
            buff[0] = carry % 10 + '0';
            carry /= 10;
          }
        }
        
        void print_perfext(unsigned p) {
          // 2**(p-1) * (2**p - 1)
          assert(p > 1 && p <= 164);
          char buff[200] = "1";
          buff_mul(buff, p);
          buff[strlen(buff) - 1]--; // Decrement, take advantage that the LSDigit is never 0
          buff_mul(buff, p - 1);
          puts(buff);
          fflush(stdout);
        }
        
        //unsigned next_prime(unsigned first_numeber_to_test_if_prime) {
        #include <stdio.h>
        
        int main() {
          unsigned p = 0;
          for (unsigned i = 0; i < 9; i++) {
           // If p prime && 2**p − 1 is prime, then 2**(p − 1) * (2**p − 1) is a perfect number.
            while (!isprime(p) || !isprime((1uLL << p) - 1))
              p++;
            printf("%2u ", p);
            print_perfext(p);
            p++;
          }
          return 0;
        }
        

        输出

         2 6
         3 28
         5 496
         7 8128
        13 33550336
        17 8589869056
        19 137438691328
        31 2305843008139952128
        61 2658455991569831744654692615953842176
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-10-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多