jeffpkamp
jeffpkamp

Reputation: 2866

C++ incorrect arithmetic results

I am writing a program using visual studios express for desktop. The portion of the program giving me trouble is made to take a hex value which is a fraction of 2^32 and convert it to an integer value and perform some simple math on it (multiplication and division) using the following bit of programming.

    if (ch == 'z')
    {
        std::string r, d;
        unsigned int ra;
        unsigned int dec, n = 1;
        r = readline;
        while (n < 9)
        {
            r = r + buffer[0];
            n++;
            ReadFile(file, buffer, sizeof(buffer), &read, NULL);
        }
        ReadFile(file, buffer, sizeof(buffer), &read, NULL);
        n++;
        while (n > 9 && buffer[0] != '#')
        {
            d = d + buffer[0];
            n++;
            ReadFile(file, buffer, sizeof(buffer), &read, NULL);
        }
        std::cout << "\n hex RA=" << r << " Hex Dec=" << d << "\n";



        std::stringstream ss,dd;
        ss << std::hex << r;
        ss >> ra;
        dd << std::hex << d;
        dd >> dec;

        std::cout << "\n ra=" << ra << " dec=" << dec << "\n";
        double RA = (ra * 86400);
        double DEC = (dec * 1296000);

        std::cout << "\n RA=" << RA << " DEC=" << DEC << "\n";
        double rRA = (RA / pow(2,32));
        double dDEC = (DEC / pow(2,32));

        std::cout << "\n RA=" << rRA << " DEC=" << dDEC << "\n";
    }

I get the following output:

 hex RA=1180C1E00 Hex Dec=0EA8A900

 ra=3435973836 dec=245934336

 RA=4294898176 DEC=1376419840

 RA2=0.999984 DEC2=0.320473

The correct values should be: (* next to values which are incorrect)

 hex RA=1180c1e00  HEX Dec=0ea8a900

 *ra=4698414592    dec=245934336

 *RA=40594302074880   *DEC=318730899456000

 *RA2=94515.9748...   *DEC2=74210.3204727...

I've thought using long int might fix the problem, but it gave the same results. I also tried using the double type for the values which gave equally bizarre results. If you can also explain why one hex conversion worked and the other didn't I would appreciate that. I am new to C++ and realize there might be something I caveat I missed when going through the many tutorials for C++. (note dec means declination, not decimal and has nothing to do with the code).

Upvotes: 0

Views: 508

Answers (2)

oknsnl
oknsnl

Reputation: 351

 hex RA=1180C1E00 Hex Dec=0EA8A900

If you can take that values as a string then the program below works as you want.

 unsigned long long int ra,dec;
stringstream ss,dd;
ss << hex << "1180C1E00";
ss >> ra;
dd << hex << "0EA8A900";
dd >> dec;

cout << "\n ra=" << ra << " dec=" << dec << "\n";
unsigned long long int RA = (ra * 86400);
unsigned long long int DEC = (dec * 1296000);

cout << "\n RA=" << RA << " DEC=" << DEC << "\n";
double rRA = RA/(pow(2.0,32));
double dDEC = DEC/(pow(2.0,32));
cout << "\n RA2=" << rRA << " DEC2=" << dDEC << "\n";
return 0;

I hope this can help.

Upvotes: 1

Igor Tandetnik
Igor Tandetnik

Reputation: 52601

Apparently, you are working on a platform where unsigned int is 32 bits large. 0x1180C1E00 doesn't fit into 32 bits. ss >> ra encounters an overflow when trying to parse this string, and fails. ra remains uninitialized; any further actions on it exhibit undefined behavior.

Also, change

double DEC = (dec * 1296000);

to

double DEC = (dec * 1296000.0);

As written, you perform arithmetic on two integers, then convert the result to double. But the result doesn't fit into unsigned int, and is wrapped around modulo 2^32 - before conversion. The change I propose converts dec to double, then performs multiplication in floating point.


With MSVC, unsigned long is 32 bits large, just like unsigned int. Using unsigned long long all around should help - it is 64 bits large.

Upvotes: 1

Related Questions