Невозможно вычислить простые множители с числом из 12 цифр в C

Я пытаюсь узнать больше о коде C, пытаясь выполнить примеры на странице Project Eular: http://projecteuler.net/problems В настоящий момент я пытаюсь вычислить наивысший простой множитель числа 600851475143. Вот мой код:

/* The prime factors of 13195 are 5, 7, 13 and 29.

What is the largest prime factor of the number 600851475143 ?*/
#include <stdio.h>

unsigned long long GetPrimeFactor(unsigned long long number)
{
    /* printf("The number you typed was %d\n", number);*/
    unsigned long long prime = 2;
    unsigned long long LargestPrime = 0;

    while (prime != 0)
    {
        if(number%prime == 0)
        {
            if(number == prime)
            {
                if(LargestPrime < prime)
                    LargestPrime = prime;

                printf("End of prime factors \nLargest Prime: %d\nEnding Number: %d\n", LargestPrime, number);
                break;
            }
            else if(LargestPrime < prime)
                LargestPrime = prime;

            //divide number by prime

            number = number/prime;
            printf("Prime: %d\n", prime);
        }

        else
        {
            //get new prime
            prime = nextPrimeNumber(prime);
        }
    }
}

unsigned long long nextPrimeNumber(unsigned long long input)
{
    unsigned long long nextPrimeNumber;

    while(input !=0)
    {
        if( input < 0)
        {
            printf("The number you have entered is negative\n");
        }
        else if (input > 0)
        {
            nextPrimeNumber = input + 1;

            if(nextPrimeNumber%2 == 0 && nextPrimeNumber != 2)
            {
                nextPrimeNumber += 1;
            }

            while(!isPrime(nextPrimeNumber))
            {
                nextPrimeNumber += 2;
            }

            return nextPrimeNumber;
        }
    }
}

int isPrime(int number)
{
    int i;
    int prime = 1; //true

    if(number == 2)
        prime = 0; //false

    if(number%2 == 0 || number <= 1)
        prime = 0;
    else
    {
        for(i=3; i<sqrt(number) && prime == 1; i+=2)
            if(number%i == 0)
                prime = 0;
    }

    return prime;
}

int main(void)
{
    unsigned long long number;

    printf("Enter a Number: \n");
    scanf("%d", &number);
    GetPrimeFactor(number);

    return 0;
}

Этот код работает для числа 13195, которое есть в примере, но не работает, когда я пробую большие числа и не уверен, что не так.

вывод с большим числом 600851475143: простое число: 3 простое число: 29 простое число: 5108231 и т. д. это не может быть правильным, потому что число в любом случае не может делиться на 3.

Не могу понять, что не так, поэтому любая помощь будет отличной


person SD1990    schedule 16.02.2012    source источник
comment
600851475143 необходимо 40 бит для представления в двоичном формате. По-видимому, ваши int имеют ширину 32 бита. Попробуйте использовать более крупный шрифт, например: long long unsigned.   -  person pmg    schedule 16.02.2012
comment
Ваши функции определены в неправильном порядке. Компилятор предполагает, что они неявно возвращают int. Это вызывает проблемы при попытке переключиться на более крупный целочисленный тип. Определите свои функции, прежде чем они будут использоваться.   -  person Pascal Cuoq    schedule 16.02.2012
comment
1) int isPrime(int number) должно быть int isPrime(unsigned long long number) 2) Есть пара мест, где вы проверяете меньше или равно. Убедитесь, что вы не настраиваете себя на провал в этих местах.   -  person JimR    schedule 16.02.2012


Ответы (2)


Подпись ints до 2147483647, unsigned ints до 4294967295, вы можете использовать unsigned long long до 18446744073709551615, а если вам нужно что-то еще большее, используйте библиотеку произвольной точности / bignum, такую ​​как GnuMP (http://gmplib.org/)

Обновите отредактированный вопрос:

Спецификатор формата для scanf, который вы используете, даже не читает весь unsigned long long, я где-то читал, что вам нужно использовать %llu, однако на моем gcc это не работает, я должен использовать:

printf("Enter a Number: \n");
scanf("%I64d", &number);
printf("%I64d", number);  // <- make sure that this prints the number you 
                 // gave it before even calling GetPrimeFactor()
person Bernd Elkemann    schedule 16.02.2012
comment
Хорошо, я попробовал это, сделав мою переменную начального числа беззнаковой длинной длинной, но теперь ее деление на 181, что снова не может произойти, но я не могу попытаться сделать все целые числа беззнаковым длинным длинным - person SD1990; 16.02.2012
comment
@ spartan2417 вы изменили вопрос, поэтому я отредактировал свой ответ. - person Bernd Elkemann; 16.02.2012
comment
спасибо за помощь, в итоге я определил свои функции вверху страницы, например, @Complicated См. биографию. и используя unsigned long long. Однако кто-то предложил вместо этого использовать uint64_t? будет ли это иметь такой же эффект? - person SD1990; 17.02.2012
comment
@ spartan2417 Попробуйте и расскажите, пожалуйста. - person Bernd Elkemann; 17.02.2012
comment
Они оба используются для очень длинных чисел, но, судя по всему, единственная разница между помещением uint64_t вместо long long заключается в том, что uint64_t может содержать 20 десятичных цифр вместо 19. - person SD1990; 21.02.2012
comment
@ spartan2417 зависит от компилятора, который работает. если вы пишете библиотеку, которую можно использовать с несколькими компиляторами, вам, вероятно, придется использовать ifdef. - person Bernd Elkemann; 21.02.2012

вы меняли scanf?

scanf("%L", &number)
person D. Cannone    schedule 16.02.2012