C program which is finding "happy" nums recursively - c

Hello guys i am trying to implement a program which is finding the happy numbers were between two numbers A and B.
Summing the squares of all the digits of the number, we replace the number with the outcome, and repeat the process. If after some steps the result is equal to 1 (and stay there), then we say that the number N is **<happy>**. Conversely, if the process is repeated indefinitely without ever showing the number 1, then we say that the number N is **<sad>**.
For example, the number 7 is happy because the procedure described above leads to the following steps: 7, 49, 97, 130, 10, 1, 1, 1 ... Conversely, the number 42 is sad because the process leads to a infinite sequence 42, 20, 4, 16, 37, 58, 89, 145, 42, 20, 4, 16, 37 ...
I try this right down but i am getting either segm faults or no results.
Thanks in advance.
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
void happy( char * A, int n);
int numPlaces (long n);
int main(void)
{
long A,B;
int npA;
char *Ap;
printf("Give 2 Numbers\n");
scanf("%li %li",&A,&B);
npA = numPlaces(A);
Ap = malloc(npA);
printf("%ld %d\n",A,npA);
//Search for happy numbers from A to B
do{
sprintf(Ap, "%ld", A);
happy(Ap,npA);
A++;
if ( npA < numPlaces(A) )
{
npA++;
Ap = realloc(Ap, npA);
}
}while( A <= B);
}
//Finds happy numbers
void happy( char * A, int n)
{
//Basic Condition
if ( n == 1)
{
if (A[0] == 1 || A[0] == 7)
printf("%c\n",A[0]);
printf("%s\n",A);
return;
}
long sum = 0 ;
char * sumA;
int nsum;
int Ai;
//Sum the squares of the current number
for(int i = 0 ; i < n;i++)
{
Ai = atoi(&A[i]);
sum = sum + (Ai*Ai);
}
nsum = numPlaces (sum);
sumA = malloc(nsum);
sprintf(sumA, "%li", sum);
happy(sumA,nsum);
free(sumA);
}
//Count digits of a number
int numPlaces (long n)
{
if (n < 0) return 0;
if (n < 10) return 1;
return 1 + numPlaces (n / 10);
}
Thanks for your time.

by the definition of your program sad numbers will cause your program to run forever
Conversely, if the process is repeated indefinitely
You need to add a stopping condition, like if I have looped for 1000 times, or if you hit a well known non terminating number (like 4) (is there a definite list of these? I dont know)

I find this solution tested and working..
Thanks for your time and I am sorry for my vagueness.
Every advice about this solution would be welcome
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
void happy( char * A, int n);
int numPlaces (long n);
int happynum = 0;
int main(void)
{
long A,B;
int npA;
char *Ap;
printf("Give 2 Numbers\n");
scanf("%li %li",&A,&B);
npA = numPlaces(A);
Ap = malloc(npA);
//Search for happy numbers from A to B
do{
sprintf(Ap, "%ld", A);
happy(Ap,npA);
if (happynum ==1)
printf("%s\n",Ap);
A++;
if ( npA < numPlaces(A) )
{
npA++;
Ap = realloc(Ap, npA);
}
}while( A <= B);
}
//Finds happy numbers
void happy( char * A, int n)
{
//Basic Condition
if ( n == 1)
{
if (A[0] == '3' || A[0] == '6' || A[0] == '9')
{
happynum = 0;
}
else
{
happynum = 1;
}
return;
}
long sum = 0;
char * sumA;
int nsum;
int Ai;
//Sum the squares of the current number
for(int i = 0 ; i < n;i++)
{
Ai = (int)(A[i]-48);
sum = sum + (Ai*Ai);
}
nsum = numPlaces (sum);
sumA = malloc(nsum);
sprintf(sumA, "%li", sum);
happy(sumA,nsum);
free(sumA);
}
//Count digits of a number
int numPlaces (long n)
{
if (n < 0) return 0;
if (n < 10) return 1;
return 1 + numPlaces (n / 10);
}

Your code uses some questionable practices. Yoe may be misguided because you are concerned about performance and memory usage.
When you allocate memory for the string, you forget to allocate one character for the null terminator. But you shouldn't be allocating, re-allocating and freeing constantly anyway. Dynamic memory allocation is expensive compared to your other operations.
Your limits are long, which may be a 32-bit or 64-bit signed integer, depending on your platform. The maximum number that can be represented with e 64-bit signed integer is 9,223,372,036,854,775,807. This is a number with 19 digits. Add one for the null terminator and one for a possible minus sign, so that overflow won't hurt, you and use a buffer of 21 chars on the stack.
You probably shouldn't be using strings inthe first place. Use the basic code to extract the digits: Split off the digit by taking the remainder of a division by 10. Then divide by 10 until you get zero. (And if you use strings with a fixed buffer size, as described above, you don't have to calculate the difits separately: sprintf returns the number of characters written to the string.
Your functions shouldn't be recursive. A loop is enough. As pm100 has noted, you need a termination criterion: You must keep track of the numbers that you have already visited. Each recursive call creates a new state; it is easier to keep an array, that can be repeatedly looked at in a loop. When you see a number that you have already seen (other than 1, of course), your number is sad.
Happy and sad numbers have this property that when your sum of squares is a number with a known happiness, the original number has this happiness, too. If you visit a known das number, the original number is sad. If you visit a known happy number, the original number is happy.
The limits of your ranges may ba large, but the sum of square digits is not large; it can be at most the number of digits times 81. In particular:
type max. number number of max. square sum dss
int 2,147,483,647 1,999,999,999 730
uint 4,294,967,295 3,999,999,999 738
long 9,223,372,036,854,775,807 8,999,999,999,999,999,999 1522
ulong 18,446,744,073,709,55,1616 9,999,999,999,999,999,999 1539
That means that when you take the sum of digit squares of an unsigned long, you will get a number that is smaller than 1540. Create an array of 1540 entries and mark all known happy numbers with 1. Then you can reduce your problem to taking the sum of digit squares once and then looking up the happiness of the number in this array.
(You can do the precalculation of the array once when you start the program.)

Related

Sum digits of number [duplicate]

This question already has answers here:
Find the sum of digits of a number(in c)
(6 answers)
Closed 2 years ago.
Hello i need problem with this task in C language. If anyone had a similar problem it would help me.
The task is:
Write a program that loads the numbers a and b (a <b), then finds and prints the numbers from the segment of [a, b] and prints the sum of the digits of each number.
I wrote for three issues, for example:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
int n1,n2,sum=0,a,b,k,n3;
scanf("%d",&a);
scanf("%d",&b);
for(k=a;k<=b;k++)
{
n1=k%10;
n2=(k/10)%10;
n3=k/100;
sum=n1+n2+n3;
printf("%d\n",sum);
}
}
The problem arises when I enter a larger than three-digit number, how to make for any number, no matter if it is two-digit, three-digit, four-digit ...
Well the way you solve this issue depends on the exact requirements. Given that you only have ints here I would use the following though it is by no meand production code
int main() {
int a = whatever;
int b = whatever;
char* a_as_s = itoa(a);
char* b_as_s = itoa(b);
int sum_of_a = 0;
int sum_of_b = 0;
for(int i = 0; a_as_s[i]; i++)
sum_of_a += atoi(a_as_s[i]);
for(int i = 0; b_as_s[i]; i++)
sum_of_b += atoi(b_as_s[i]);
}
That should calculate the sum of digits for arbirary lengths - the rest of your code seems fine
You've already solved the iterating part so as people have suggested in the comments all you need now is a way to sum the digits of an arbitrary integer. I've modified your solution with my take on the problem. I'm pretty sure there is a more elegant/efficient way to do this, so I'd suggest you also check out the links people have provided in the comments. Anyhow here is my take:
#include <stdio.h>
int maxPowOf10(int num)
{
int divisor = 1;
for(;;)
{
if(num / divisor == 0)
{
break;
}
divisor *= 10;
}
return divisor / 10;
}
int sumOfDigits(int num)
{
int sum = 0;
for(int divisor = maxPowOf10(num); divisor >= 1; divisor /= 10)
{
int tmp = num / divisor;
sum += tmp;
num -= tmp * divisor;
}
return sum;
}
int main()
{
int n1,n2,sum=0,a,b,k,n3;
printf("Insert a: ");
scanf("%d",&a);
printf("Insert b: ");
scanf("%d",&b);
printf("Result\n");
for(k=a;k<=b;k++)
{
sum = sumOfDigits(k);
printf("number: %d sum of its digits: %d\n", k, sum);
}
return 0;
}
The approach is fairly straightforward. To find the sum of the digits, first you determine what is the largest power of 10 that still features in the number. Once that is found we can just divide by the largest power of 10 and add the result to sum. The trick is that, after that, we have to remove the part of the number that is described by the decimal place we are at. So we don't count it again. Then, you keep repeating the process for ever decreasing powers of 10. In the end you have the complete sum.
To illustrate this on 152 for example:
a) The largest power of 10 in 152 is 100.
b1) We divide 152 by 100 and get 1. We add 1 to sum. We also decrease the number to 52 (152 - 100)
b2) We divide 52 by 10 and get 5. We add 5 to sum. We decrease the number to 2 (52 - 50).
b3) We divide 2 by 1 and get 2. We add 2 to sum. We decrease the number to 0 (2 - 2).
Point a describes the method maxPowOf10
Point b describes the method sumOfDigits

How do I save the return array from a function?

I'm currently learning c (just starting), and I'm trying to create a program that finds all the integers with 10 digits, with the conditions:
the first digit can be divided by 1;
the number represented by the first two digits can be divided by 2;
etc.
For example, the number 1295073846 doesn't make the cut, because 1295 is not divisible by 4 (but 1 is divisible by 1, 12 by 2, and 129 by 3).
I understand how this can be done, but I'm still struggling to manipulate arrays and pointers. Here is my code (only numToArr and the beginning of findn() should be relevant):
int numToArr(long num) { // splits a given number into an array of 10 digits
int arr[10];
int i = 9;
do {
arr[i] = num % 10;
num /= 10;
i--;
} while (num != 0);
printf("%d%d%d\n", arr[0], arr[1], arr[2]);
return *arr;
}
int join(char s[3], int n1, int n2) { // so I can get the combination of digits
snprintf(s, 3, "%d%d", n1, n2);
int n12 = atoi(s);
return n12;
}
int findn() { // the output will be the list of numbers, but I'm testing with 1292500000
long nmin = 1000000000;
long nmax = 9999999999;
int *arr;
for(int i = nmin; i <= nmax; i++) {
*arr = numToArr(1292500000l);
// I know I can optimize this part, will work on it later
if(arr[0] % 1 != 0) // if the first digit is not divisible by one, skip to the next number
continue;
else { // if it is, check for the combination of the first two digits
char s12[3];
int n12 = join(s12, arr[0], arr[1]);
printf("%d\n", n12);
break;
...
When I do
*arr = numToArr(1292500000l);
the array doesn't have the correct digits (arr[0] should be 1, arr[1] should be 2 (but it's zero)).
I've tried messing with pointers and everything I could find online to solve this issue, but nothing works. Any help would be appreciated!
Thank you.

Finding numbers with unique digits in C

I have to write a program that finds every number (except 0) which can be factored by numbers from 2-9.
For example first such a number would be number 2520 as it can be divided by every single number from 2 to 9.
It also has to be a number that contains only 1 type of digit of its own (no multiple digits in a number). So for example 2520 will not meet this requirement since there are two same digits (2). The example of a number that meets both requirements is number 7560. That is the point I don't how to do it. I was thinking about converting value in an array to string, and then putting this string in another array so every digit would be represented by one array entry.
#include <stdio.h>
#include <math.h>
int main() {
int i, n, x, flag, y = 0;
scanf("%d", &n);
double z = pow(10, n) - 1;
int array[(int)z];
for (i = 0; i <= z; i++) {
flag = 0;
array[i] = i;
if (i > 0) {
for (x = 2; x <= 9; x++) {
if (array[i] % x != 0) {
flag = 1;
}
}
if (flag == 0) {
y = 1;
printf("%d\n", array[i]);
}
}
}
if (y == 0) {
printf("not exist");
}
return 0;
}
This should give you a base:
#include <stdio.h>
#include <string.h>
int main()
{
char snumber[20];
int number = 11235;
printf("Number = %d\n\n", number);
sprintf(snumber, "%d", number);
int histogram[10] = { 0 };
int len = strlen(snumber);
for (int i = 0; i < len; i++)
{
histogram[snumber[i] - '0']++;
}
for (int i = 0; i < 10; i++)
{
if (histogram[i] != 0)
printf("%d occurs %d times\n", i, histogram[i]);
}
}
Output:
Number = 11235
1 occurs 2 times
2 occurs 1 times
3 occurs 1 times
5 occurs 1 times
That code is a mess. Let's bin it.
Theorem: Any number that divides all numbers in the range 2 to 9 is a
multiple of 2520.
Therefore your algorithm takes the form
for (long i = 2520; i <= 9876543210 /*Beyond this there must be a duplicate*/; i += 2520){
// ToDo - reject if `i` contains one or more of the same digit.
}
For the ToDo part, see How to write a code to detect duplicate digits of any given number in C++?. Granted, it's C++, but the accepted answer ports verbatim.
If i understand correctly, your problem is that you need to identify whether a number is consisted of multiple digits.
Following your proposed approach, to convert the number into a string and use an array to represent digits, i can suggest the following solution for a function that implements it. The main function is used to test the has_repeated_digits function. It just shows a way to do it.
You can alter it and use it in your code.
#include <stdio.h>
#define MAX_DIGITS_IN_NUM 20
//returns 1 when there are repeated digits, 0 otherwise
int has_repeated_digits(int num){
// in array, array[0] represents how many times the '0' is found
// array[1], how many times '1' is found etc...
int array[10] = {0,0,0,0,0,0,0,0,0,0};
char num_string[MAX_DIGITS_IN_NUM];
//converts the number to string and stores it in num_string
sprintf(num_string, "%d", num);
int i = 0;
while (num_string[i] != '\0'){
//if a digit is found more than one time, return 1.
if (++array[num_string[i] - '0'] >= 2){
return 1; //found repeated digit
}
i++;
}
return 0; //no repeated digits found
}
// test tha function
int main()
{
int x=0;
while (scanf("%d", &x) != EOF){
if (has_repeated_digits(x))
printf("repeated digits found!\n");
else
printf("no repeated digits\n");
}
return 0;
}
You can simplify your problem from these remarks:
the least common multiple of 2, 3, 4, 5, 6, 7, 8 and 9 is 2520.
numbers larger than 9876543210 must have at least twice the same digit in their base 10 representation.
checking for duplicate digits can be done by counting the remainders of successive divisions by 10.
A simple approach is therefore to enumerate multiples of 2520 up to 9876543210 and select the numbers that have no duplicate digits.
Type unsigned long long is guaranteed to be large enough to represent all values to enumerate, but neither int nor long are.
Here is the code:
#include <stdio.h>
int main(void) {
unsigned long long i, n;
for (n = 2520; n <= 9876543210; n += 2520) {
int digits[10] = { 0 };
for (i = n; i != 0; i /= 10) {
if (digits[i % 10]++)
break;
}
if (i == 0)
printf("%llu\n", n);
}
return 0;
}
This program produces 13818 numbers in 0.076 seconds. The first one is 7560 and the last one is 9876351240.
The number 0 technically does match your constraints: it is evenly divisible by all non zero integers and it has no duplicate digits. But you excluded it explicitly.

Counting powers of 3 within a given range in C

I have to write a program that takes in two positive integers, start and end, where (1 < start < end). Then the program would look within this range [start, end] and count the number of powers of 3.
So, for example, if start is 2 and end is 10, the output would be 2. (as 3 and 9 are powers of 3).
Below is my code:
#include <stdio.h>
#include <math.h>
int main(void) {
int start, end, i, count = 0;
printf("Enter start and end: ");
scanf("%d %d", &start, &end);
for (i = start; i <= end; i++) {
if ((log(i) / log(3)) == floor((log(i) / log(3)))) {
printf("%d\n", i);
count++;
}
}
printf("Answer = %d\n", count);
return 0;
}
But, when I tried to run one of the test cases [3, 1000], the output is 5, when it should be 6.
3
9
27
81
729
Answer = 5
The number 243 is missing. Is there something wrong with my code?
The problem is you are using exact comparison of floating point numbers. Specifically, here:
if ((log(i)/log(3)) == floor((log(i)/log(3))))
Since log() and floor() return double, you're comparing without any tolerance two values which cannot be compared that way.
How should I do floating point comparison?
Your immediate problem has to do with the imprecision of floating point numbers, something that is generally well documented on the net, including various methods useful in fixing that problem.
However, I'm not actually going to bother referring you to them because the use of floating point is totally unnecessary here. There's a much more efficient way of doing this that involves only integers.
Rather than going through numbers in your range looking for powers of three using floating point operations, you would be better off going through powers of three (using just integer multiplication) looking for numbers in your range.
In pseudo-code, that would go something like:
powerOfThree = 1
while powerOfThree <= endRange:
if powerOfThree >= startRange:
print powerOfThree
powerOfThree = powerOfThree * 3
You could even make it more efficient by selecting a more suitable starting value for powerOfThree but, since there are only 40-odd powers of three in a 64 bit number, that's probably a waste of time.
When converting from pseudo-code to the more concrete C, you unfortunately come across the limitations of the datatypes in that language, specifically the fact that multiplication may result in overflow.
There are various ways you can avoid this this such as detecting that it's about to happen and exiting the loop early.
Given below is the function that you need, one which handles this issue, along with some test code which can be used for validating it.
#include <stdio.h>
#include <limits.h>
// I hate typing :-)
typedef unsigned long ULONG;
typedef unsigned int UINT;
static UINT countPowersOfThreeBetween (ULONG low, ULONG high) {
// Catch invalid params, just exit with zero.
if (low > high) return 0;
// Go through all powers of three.
ULONG powerOfThree = 1;
UINT count = 0;
do {
// If within your range, count it.
if ((powerOfThree >= low) && (powerOfThree <= high)) {
count++;
// printf ("DEBUG: got %lu\n", powerOfThree);
}
// Early exit if about to overflow.
if (ULONG_MAX / powerOfThree < 3) break;
// Advance to next power and continue if within range.
powerOfThree *= 3;
} while (powerOfThree <= high);
// Notify caller of count.
return count;
}
// Test function to make test suite easier.
static void testRange (ULONG low, ULONG high) {
UINT count = countPowersOfThreeBetween (low, high);
printf ("In range %lu..%lu, found %u occurrences\n", low, high, count);
}
// Test suite, add whatever you need.
int main (void) {
testRange (1000, 10);
testRange (0, 0);
testRange (9, 9);
testRange (3, 1000);
testRange (0, ULONG_MAX);
testRange (ULONG_MAX, ULONG_MAX);
return 0;
}
As you will see from the output, this gives the correct counts for various ranges:
In range 1000..10, found 0 occurrences
In range 0..0, found 0 occurrences
In range 9..9, found 1 occurrences
In range 3..1000, found 6 occurrences
In range 0..18446744073709551615, found 41 occurrences
In range 18446744073709551615..18446744073709551615, found 0 occurrences
And, if you uncomment the printf line in countPowersOfThreeBetween(), you'll also see the actual values detected.
Before choosing floating point types in the future, I strongly recommend you read this article entitled "What every computer scientist should know about floating-point arithmetic", by David Goldberg. It explains your problem(s) nicely, much better than I could have.
You don't actually need floating point (or negative integer) types here, so they should be avoided. Form your powers by multiplication, rather than addition:
#include <assert.h>
#include <limits.h>
#include <stdio.h>
int main(void){
unsigned int start, end, i, count = 0;
printf("Enter start and end: ");
int x = scanf("%u %u", &start, &end);
assert(x == 2); // XXX: INSERT PROPER ERROR HANDLING!
// find the first power greater than or equal to start
for (i = 1; i < start && UINT_MAX / 3 >= i; i *= 3);
// ... then count each one less than or equal to end
while (i <= end && UINT_MAX / 3 >= i) {
printf("%u\n", i);
i *= 3;
count++;
}
printf("Answer = %u\n", count);
}
Your problem is round-off error while float calculating in computer, the result of log(243)/log(3) is not exactly log3(243), where computer store approximate value of it. eg, in my 32bit computer, it is 4.99999999999999911182.
However, you have two ways to solve it,
use integer calculation instead of float.
simple mathematical transformation.
number of powers of 3 in [start, end] is equivalent to floor(log3(end)-log3(start))+1, wrote in c is
printf("answer:%d\n", (int)((log(1000)-log(3))/log(3))+1);
complete code:
#include <stdio.h>
#include <math.h>
int pow3(int n) {
int ret = 1;
while(n--) {
ret *= 3;
}
return ret;
}
int main() {
int a, start, end, answer;
scanf("%d%d", &start, &end);
a = (int)(log(start+0.5)/log(3));
//printf("%d,%d,%d\n", a, pow3(a), start);
if(start == end) answer = (start == pow3(a));
else answer = (int)((log(end+0.5)-log(start))/log(3))+1;
printf("answer = %d\n", answer);
}
Result:
Input[0]: 2 10
Output[0]: 2
Input[1]: 1 3
Output[1]: 2
Input[2]: 3 1000
Output[2]:6
Your program fails because of floating point precision issues.
Use integer arithmetics instead:
#include <limits.h>
#include <stdio.h>
int main(void) {
unsigned int start, end, i, count;
printf("Enter start and end: ");
if (scanf("%u %u", &start, &end) == 2) {
for (i = 1, count = 0; i <= end && i <= UINT_MAX / 3; i *= 3) {
if (i >= start) {
printf("%u\n", i);
count++;
}
}
printf("Answer = %u\n", count);
}
return 0;
}
A direct solution with floating point arithmetics is possible too:
#include <math.h>
#include <stdio.h>
int main(void) {
unsigned int start, end, count = 0;
printf("Enter start and end: ");
if (scanf("%u %u", &start, &end) == 2) {
if (end > 0 && end >= start) {
int start3 = (start <= 1) ? 0 : (int)(log(start - 0.5) / log(3));
int end3 = (int)(log(end + 0.5) / log(3));
count = end3 - start3;
}
printf("Answer = %u\n", count);
}
return 0;
}

Tricky and confusing C program about divisor sum and perfect numbers

The assignment is :
Write a program that calculates the sum of the divisors of a number from input.
A number is considered perfect if the sum of it's divisiors equal the number (ex: 6 = 1+2+3 ;28 = 1 + 2 + 4 + 7 +14).
Another definition:
a perfect number is a number that is half the sum of all of its positive divisors (including itself)
Generate the first k perfect numbers (k<150).
The main problem with this is that it's confusing the two asking points don't really relate.
In this program i calculated the sum of divisors of an entered number, but i don't know how to relate it with the second point (Generate the first k perfect numbers (k<150)).
#include <stdio.h>
#include <stdlib.h>
main()
{
int x,i,y,div,suma,k;
printf("Introduceti numarul\n"); \\enter the number
scanf("%d",&x);
suma=0; \\sum is 0
for(i=1;i<=x;i++)
{
if(x%i==0)
suma=suma+i; \\sum=sum+i;
}
printf("Suma divizorilor naturali este: %d\n",suma); \\the sum of the divisors is
for(k=1;k<150;k++) \\ bad part
{
if (x==suma)
printf("%d",k);
}
}
Suppose you have a function which can tell whether a given integer is perfect or not:
int isPerfect(int);
(function body not shown)
Now your main program will look like:
int candidate;
int perfectNumbers;
for(candidate = 1, perfectNumbers = 0; perfectNumbers < 150; candidate++) {
if (isPerfect(candidate)) {
printf("Number %d is perfect\n", candidate);
perfectNumbers++;
}
}
EDIT
For the same program without functions:
int candidate;
int perfectNumbers;
for(candidate = 1, perfectNumbers = 0; perfectNumbers < 150; candidate++) {
[... here your algorithm to compute the sum of the divisors of "candidate" ...]
if (candidate*2 == sum_of_divisors) {
printf("Number %d is perfect\n", candidate);
perfectNumbers++;
}
}
EDIT2: Just a note on perfect numbers
As noted in the comments section below, perfect numbers are very rare, only 48th of them are known as of 2014. The sequence (A000396) also grows very fast: using 64-bit integers you'll be able to compute up to the 8th perfect number (which happen to be 2,305,843,008,139,952,128). In this case the variable candidate will wrap around and start "finding" "new" perfect numbers from the beginning (until 150 of them are found: actually 19 repetitions of the only 8 findable in 64-bit integers). Note though that your algorithm must not choke on a candidate equals to 0 or to negative numbers (only to 0 if you declare candidate as unsigned int).
I am interpreting the question to mean generate all numbers under 150 that could are perfect numbers.
Therefore, if your program works for calculating perfect numbers, you keep calculating them until the starting number is >= 150.
Hope that makes sense.
Well, here's my solution ..
First, you have to make a reliable way of getting divisors.Here's a function I made for that:
size_t
getdivisors(num, divisors)
long long num;
long long *divisors;
{
size_t divs = 0;
for(long long i = num; i > 0; --i)
if (num%i == 0)
divisors[divs++] = i;
return divs;
}
Second, you need to check if the number's divisors match the perfect number's divisors properties (the sum of them is half the number).
Here's a second function for that:
bool
isperfect(num)
long long num;
{
long long divisors[num/2+1];
size_t divs = getdivisors(num, divisors);
if (divs == 0)
return false;
long long n = 0;
for(int i = 1; i < divs; ++i)
n += divisors[i];
return (n == num);
}
Now, from your question, I think you need to print all perfect numbers less than 150, right ?
See this:
int
main(argc, argv)
int argc;
char ** argv;
{
for(int i = 1; i < 150; ++i)
if (isperfect(i))
printf("%d is perfect.\n", i);
return 0;
}
I hope that answers your question ..

Resources