Reputation: 2866
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
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
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