如何从 C 中的用户给定数字打印 10 个完美数字?
How to print 10 perfect numbers from a user given number in C?
我不知道如何打印下十个 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
我刚开始编码。任何帮助将不胜感激。
你必须在找到完全数后放置计数器,所以增加 c
必须发生在检查完全数的 if
语句中,如下所示:
if(sum==n){
printf("%d",n);
c++;
}
在此之后你需要增加数字,称为 n,像这样:
n++;
根据这些数字,@Jonathan Leffler 是对的,您应该使用适当的变量。
根据你写的输出,我相信你想显示 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,因为它会花费太多时间
几个人提到的整数溢出问题很重要,但次要。即使我们修复了您损坏的逻辑,并调整它以处理更大的固定大小的整数:
#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, and their relationship to perfect numbers, as well as the Lucas-Lehmer test。这种方法需要更多的思考,但令人惊讶的是,代码并不多。并且会更快地产生更多结果(尽管最终也会陷入困境。)
Research,分而治之
完全数的形式为 2p − 1 * (2p − 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 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
我不知道如何打印下十个 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
我刚开始编码。任何帮助将不胜感激。
你必须在找到完全数后放置计数器,所以增加 c
必须发生在检查完全数的 if
语句中,如下所示:
if(sum==n){
printf("%d",n);
c++;
}
在此之后你需要增加数字,称为 n,像这样:
n++;
根据这些数字,@Jonathan Leffler 是对的,您应该使用适当的变量。
根据你写的输出,我相信你想显示 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,因为它会花费太多时间
几个人提到的整数溢出问题很重要,但次要。即使我们修复了您损坏的逻辑,并调整它以处理更大的固定大小的整数:
#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, and their relationship to perfect numbers, as well as the Lucas-Lehmer test。这种方法需要更多的思考,但令人惊讶的是,代码并不多。并且会更快地产生更多结果(尽管最终也会陷入困境。)
Research,分而治之
完全数的形式为 2p − 1 * (2p − 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 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