#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;
}
}
This code has four functions.
The prime
function checks if a number is prime or not; it returns 0 when it is prime and 1 if it is not.
The perfect
function checks if a number is perfect or not; it returns 1 if it is perfect and 2 if it is not.
The armstrong
function checks if a number is Armstrong or not; it returns 2 if Armstrong and 3 if not.
The checknumber
function checks if the number is a prime, Armstrong, or perfect number. and it returns:
0 if the number is prime.
1 if the number is perfect.
2 if the number is Armstrong.
3 if the number is Armstrong & prime.
4 if the number is Armstrong & perfect.
5 Otherwise.
In the main
function,
I made an infinite loop to ask the user for the number he wants to check, and after checking it, I asked the user if he wanted to check another number or not. I also made a switch
for the checknumber
function to print the number that was entered, for example:
The user enters 7, the output is:
This number is Armstrong & Prime.
Want to check another number? (1) to continue; (0) to close.
The problem is that when I use this number (28116440335967) to check, the program never produces any output, and I don't know why.
You need a more efficient algorithm to check for prime numbers and perfect numbers: as coded, you iterate up to n / 2 times in the prime()
function and n times for the perfect()
function.
Since 28116440335967
is a prime number, prime(x)
takes a long time and perfect(x)
even longer, which explains the lack of output: the program is just running full speed but takes too long.
You can reduce the complexity of both functions by iterating only up to the square root of 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;
}
}
Note also these remarks:
it is very confusing for the prime()
function to return 0
is the number is prime and 1
otherwise.
it would be much more intuitive for prime()
, armstrong()
and perfect()
to return 0
if the number is not prime, Armstrong or perfect respectively and 1
if it is.
using a combination of binary indicators for the CheckNumber()
return value would make the code both simpler and more readable.
it is recommended to use integer arithmetics for the armstrong()
function to avoid accuracy issues in functions log10
and pow
.
Here is a modified version:
#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;
}