简体   繁体   中英

C++ code outputting negative values

I wrote up a solution for a puzzle-type website. On XCode with the latest g++, my code compiles fine. On their website (and codepad), my output is negative. Could someone help me understand why, because I'm honestly stumped.

#include <iostream>
#include <cmath>
#include <vector>
#include <map>

using namespace std;

vector<int> getAllPrimes(vector<int> primesArray, int n)
{
    vector<int> numArray (n+1, 1);

    for (int i = 2; i <= n; i++)
    {
        if (numArray[i] == 1)
        {
            primesArray.push_back(i);
            for (int k = i; k <= n; k+= i)
            {
                numArray[k] = 0;
            }
        }
    }

    return primesArray;
}

int main()
{
    long n = 32327;

    if (n == 1)
    {
        printf("%ld\n", n);
        return EXIT_SUCCESS;
    }


    map <int, int> primeMap;
    map <int, int>::iterator itr;
    vector<int> primesArray;

    primesArray = getAllPrimes(primesArray, n);

    while(!primesArray.empty())
    {
        long currPrime = primesArray.back(), curr = currPrime;
        while (currPrime <= n)
        {
            primeMap[curr] += (int)floor(n/currPrime);
            currPrime *= curr;   //multiply currPrime to add another factor of curr. 
        }
        primesArray.pop_back();
    }

    //get the number of divisors of n!
    long numDivisors = 1;
    for (itr=primeMap.begin(); itr != primeMap.end(); itr++)
    {
        numDivisors *= ((*itr).second*2)+1;     //power of each prime + 1, * 2 because you need the number of divisors of the square of n!
        numDivisors = numDivisors % 1000007;
    }

    printf("%ld\n", numDivisors);

    return 0;
}

Ordinarily "long n" is supposed to read an integer between 1 and 1 million from standard input, but I just assigned a value to simulate it.

I have put the code in codepad here: http://codepad.org/RpPFuLzX . As you can see, the output is -596936 , whereas on my machine it is 656502 (which is the correct output). What exactly is going on?

Very likely culprit is that CodePad and the other site are compiling on a 32-bit system, where a long is 4 bytes long ( http://codepad.org/W00vCFIN ). On OS X, everything defaults to 64-bit, and on those systems (but not Windows), a long is 8 bytes long. As such, you are overflowing a computation at some point.

If you depend on a specific integer size, use stdint.h

Here is an adapted version which matches your expected output, using an int64_t : http://codepad.org/Owsl3ClR

The reason why you get different results is that data types like long are treated differently on 32 bit and 64 bit. Mac OS X uses the LP64 data model where a long is 64 bits long in 64 bit mode and 32 bits long in 32 bit mode. If you build your program for 32 bit and 64 bit separately you will see different results.

A popular solution is to use data types which specify the number of bits, like uint64_t for unsigned integers of size 64 bits instead of long which according to the standard is just equal to or larger than int .

Pasting to Comeau online , I get:

"ComeauTest.c", line 49: error: more than one instance of overloaded function
          "floor" matches the argument list, the choices that match are:
            function "floor(long double)"
            function "floor(float)"
            function "floor(double) C"
            function "std::floor(long double)"
            function "std::floor(float)"
            The argument types that you used are: (long)
              primeMap[curr] += (int)floor(n/currPrime);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM