0

There is a logic flaw within my code that I can't seem to pass 2^31 − 1 as an input. Here is a fragment of my code.

#include <stdio.h>
int main() {
long input = 0;
long temp = 0;
int count = 0;
printf("Enter a positive integer ( or 0 to quit): ");
scanf("%ld", &input);
if(input == 0)
{
    printf("Quit.");
}
else
{
    temp = input;
    while (temp != 1)
    {
        if(temp %2 ==0)
        {
            temp = temp/2;
            count++;


        } else
        {
            temp = 3*temp + 1;
            count++;
        }

    }
return 0;
}

I have tried changing the size of my input to long => long long and it still get stuck within this area after Debugging it. Please provide some feedback Thanks!

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
user2805478
  • 9
  • 1
  • 5
  • Hey, could it be that you have proven the Collatz conjecture is false? Naah.. – Eugene Sh. Sep 30 '16 at 17:15
  • How about printing `temp` in the loop and see what's happening? – Bo Persson Sep 30 '16 at 17:16
  • 1
    It can just overflow the `temp` at some point. – Eugene Sh. Sep 30 '16 at 17:17
  • What happens, and what do you want it to do? There is a limit to what an integer can contain, and `INT_MAX * 3 + 1` is well beyond that limit. –  Sep 30 '16 at 17:18
  • I want it to count the steps it takes to solve the Conjecture, but after finding out executing this the number becomes random at some point within the loop and basically stays there for ever.... I have tried this on python and it took 450 steps to solve this number. – user2805478 Sep 30 '16 at 17:39
  • Have you actually read the comments? – Eugene Sh. Sep 30 '16 at 17:43
  • For one thing, using unsigned numbers will increase their range, because the value is always positive. For another, is `long` the same size as `int` on your system? It is on mine. What about using `unsigned long long` or `uint64_t`? – Weather Vane Sep 30 '16 at 17:52
  • Eugene I'm aware of the overflow, but I'm puzzled about it even after expanding the range. Also I tried to expand it to long unsigned but the amount of steps does not match up with the code in python, but I'll see if adding another long would make a difference. Thanks – user2805478 Sep 30 '16 at 18:09
  • Please use the format such as @WeatherVane with their whole name when directing a comment to someone. That will raise a flag for their attention. – Weather Vane Sep 30 '16 at 18:22

2 Answers2

0

Assuming your system has a long of 64 bits, then changing it to work with unsigned long, including scanf(), seems to work fine:

#include <stdio.h>
#include <assert.h>

int main() {
    unsigned long input;
    assert(sizeof(input) * 8 >= 64);

    while (1) {
        printf("Enter a positive integer (or 0 to quit): ");
        (void) scanf("%lu", &input);

        if (input == 0) {
            break;
        }

        unsigned int count = 0;

        while (input != 1) {
            if (input % 2 == 0) {
                input /= 2;
            } else {
                input = 3 * input + 1;
            }
            count++;
        }

        printf("%d\n", count);
    }

    printf("Quit.\n");

    return 0;
}

USAGE

> ./a.out
Enter a positive integer (or 0 to quit): 2147483647
450
Enter a positive integer (or 0 to quit): 0
Quit.
>

Otherwise, find some other 64 bit type (long long?) to use. Python works as it has infinitely large integers.

cdlane
  • 40,441
  • 5
  • 32
  • 81
0

A long int does not necessarily have to have more than 32 bits. To ensure you are using 64-bit integers, it is best to use the int64_t type from inttypes.h, and to use the PRId64 macro instead of ld in the call to scanf().

Still, on any normal desktop system you should get at least a 32-bit int here. But, the problem is in this line of code:

temp = 3 * temp + 1;

If input is 2^31-1, then this will overflow a 32-bit int.

G. Sliepen
  • 7,637
  • 1
  • 15
  • 31