代码之家  ›  专栏  ›  技术社区  ›  jeffpkamp

C++错误的算术结果

  •  0
  • jeffpkamp  · 技术社区  · 10 年前

    我正在使用桌面版visual Studio express编写程序。程序中给我带来麻烦的部分是取一个十六进制值,它是2^32的一部分,然后将其转换为一个整数值,并使用以下编程位对其执行一些简单的数学运算(乘法和除法)。

        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";
        }
    

    我得到以下输出:

     hex RA=1180C1E00 Hex Dec=0EA8A900
    
     ra=3435973836 dec=245934336
    
     RA=4294898176 DEC=1376419840
    
     RA2=0.999984 DEC2=0.320473
    

    正确的值应为:(不正确值旁边的*)

     hex RA=1180c1e00  HEX Dec=0ea8a900
    
     *ra=4698414592    dec=245934336
    
     *RA=40594302074880   *DEC=318730899456000
    
     *RA2=94515.9748...   *DEC2=74210.3204727...
    

    我认为使用long int可能会解决这个问题,但它给出了相同的结果。我还尝试对值使用double类型,这会产生同样奇怪的结果。如果你也能解释为什么一个十六进制转换有效而另一个无效,我会很感激。我是C++新手,我意识到在阅读C++的许多教程时,我可能会遗漏一些东西。(注意dec表示赤纬,而不是十进制,与代码无关)。

    2 回复  |  直到 10 年前
        1
  •  1
  •   Igor Tandetnik    10 年前

    显然,你在一个平台上工作 unsigned int 是32位大。 0x1180C1E00 不适合32位。 ss >> ra 尝试解析此字符串时遇到溢出,并失败。 ra 保持未初始化状态;对它的任何进一步操作都表现出未定义的行为。

    此外,改变

    double DEC = (dec * 1296000);
    

    double DEC = (dec * 1296000.0);
    

    如前所述,您对两个整数执行算术运算,然后将结果转换为双倍。但结果并不符合 无符号整型 ,并在转换之前围绕模2^32进行包装。我提议的改变改变了 dec 然后执行浮点乘法。


    利用MSVC, unsigned long 32位大,就像 无符号整型 .使用 unsigned long long 所有这些都应该有所帮助——它是64位大。

        2
  •  1
  •   oknsnl    10 年前
     hex RA=1180C1E00 Hex Dec=0EA8A900
    

    如果您可以将这些值作为字符串,那么下面的程序将按您的需要工作。

     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;
    

    我希望这能有所帮助。