开发者

Euler Problem 3 - I need help with this small piece of C

I have started solving the problems of http://projecteuler.net/, but I can't seem to work out problem # 3. I think it will be fairly easy for the most of you.

#include <stdio.h>
#include <stdbool.h>  //This is to bring in the define of true
#include <math.h>  //This is to bring in the define of sqrt()

int LargestFactor (long number);
bool IsItPrime (int number);

int main (int argc, const char * argv[]) {
    long number;
    number = 6008514751开发者_如何学C43;
    printf("The largest prime factor of %ld is %d.", number, LargestFactor(number));
}


int LargestFactor (long number) {
    int divider,i=1;
    bool foundIt=false;
    while (foundIt == false) {
        i++;
        if (number % i == 0 && IsItPrime(number/i)) {
            divider = number / i;
            foundIt=true;
        }
    }
    return divider;
}


bool IsItPrime (int number) {
    int i=1;
    bool isPrime=true;
    while (i<sqrt(number) && isPrime == true) {
        i++;
        if (number % i == 0) {
            isPrime=false;
        }
    }
    return isPrime;
}

also I get this result:

The largest prime factor of 600851475143 is -127237759.


The problem is that there is a maximum value that the long type can hold, and when you try to store a number larger than the max that type you can hold you may get negative results because of the 2's compliment system.

Refer to this page: http://en.wikipedia.org/wiki/Limits.h

Which will show you the guaranteed minimum values the data types will hold.

So, you should declare number in this way: long long int number = 600851475143LL

So that it will be large enough to hold the number.


The number 600851475143 is greater than INT_MAX when the integer is represented with 32-bit (which is the case on most common platform). You should probably change all your variables and return values from int to uint64_t (from stdint.h). Moreover, you should change your immediate value to 600851475143LL so that it is not casted to int by the compiler.


Like others said, you need to use 64 bit integers. You should also use %lld in your printf. And ideally avoid using sqrt and libm by changing your while statement to:

while ((i*i)<number && isPrime == true) {


You need to look at your integral type sizes. Your original number is about 600 billion, which won't fit in a 32-bit integer. What happens with signed overflow is technically undefined, but most modern systems will make a stab at modular arithmetic for you.

On some systems, long is 32 bits, and 64 bits (which will work for your use here). Assuming you have some C99 on your platform, long long is at least 64 bits. Use it.

Be careful of intermediate results also. You're using int in some of your processing (i and divider from LargestFactor, and you're even passing an int to IsItPrime). Use long long for all variables involved in the calculation, or you'll be truncating part of your values sometimes.

And, as Sylvain Defresne suggested, put LL at the end of your numeric literal. It's at least clearer that way.

If your number has large prime factors, you're going to have problems with your algorithm, since it will seem to take forever, but that would be a separate question.


Instead only long.. you can also use long long and double long. so that you get the answer in positive sign.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜