[英]How to print 10 perfect numbers from a user given number in C?
我不知道如何打印接下來的十個完美數字。 這是我到目前為止所得到的:
#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;
}
我目前收到的 output:
input: 2 (say)
output: 6
我想要的是:
input: 2
output:
6
28
496
8128
33550336
858986905
137438691328
2305843008139952128
2658455991569831744654692615953842176
191561942608236107294793378084303638130997321548169216
我剛剛開始編碼。 任何幫助將不勝感激。
幾個人提到的 integer 溢出問題很重要,但次要。 即使我們修復了您損壞的邏輯,並對其進行調整以處理更大、固定大小的整數:
#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
主要問題是您使用了錯誤的算法。 閱讀梅森素數及其與完美數的關系,以及盧卡斯-萊默檢驗。 這種方法需要更多的思考,但令人驚訝的是,沒有更多的代碼。 並且會更快地產生更多結果(盡管最終也會陷入困境。)
找到完美數后必須放置計數器,因此在檢查完美數的if
語句中必須增加c
,如下所示:
if(sum==n){
printf("%d",n);
c++;
}
在此之后,您需要增加稱為 n 的數字,如下所示:
n++;
根據數字,@Jonathan Leffler 是對的,您應該使用適當的變量。
從 output 你寫我相信你想顯示 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,因為它會花費太多時間
研究,分而治之
完美數的形式為 2 p - 1 * (2 p - 1)。
代碼需要擴展精度才能形成191561942608236107294793378084303638130997321548169216
提高效率
迭代到<= n / 2
需要很長時間。 迭代到<= 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 素數檢驗
下面的代碼適用於除第 10 個完美數字之外的所有數字,因為代碼必須測試 isprime(2 67 - 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;
}
Output
2 6
3 28
5 496
7 8128
13 33550336
17 8589869056
19 137438691328
31 2305843008139952128
61 2658455991569831744654692615953842176
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.