将表示小数的int转换为double

时间:2016-07-13 21:33:28

标签: c++ type-conversion precision

将表示小数的int转换为double的正确方法是什么?

我有一个int代表例如12,123456为12123456.这来自一个我无法改变的网络设备。

我希望将其转换为双倍且误差最小。

天真的解决方案是: double res = boost::numeric_cast<double>(myint) / 1000000.0;

我认为将myint(一个巨大的数字)转换为double比其他方法更有损,因为结果值接近1,dobule的精度更高。

我正在寻找进行此转换的最小损失方法。

编辑:

我不相信log0的答案是对的。 TL; DR 他是。

我使用的测试:

#include <iostream>
#include <limits>

#include <boost/random.hpp>


inline double DecimalToDouble( int64_t value, int64_t divisor )
{
    int64_t first =  value / divisor;
    int64_t second = value % divisor;

    return (double)first + (double)second / (double)divisor;
}

int main()
{
    boost::mt19937 rng;
    boost::uniform_int<int> distr( std::numeric_limits<int>::min(),
        std::numeric_limits<int>::max() );
    boost::variate_generator< boost::mt19937, boost::uniform_int<> > dice( rng, distr );

    int erra = 0;
    int errb = 0;
    std::cout.precision( std::numeric_limits<double>::max_digits10 );

    int iterations = 1000000;
    for( int i = 0; i < iterations; ++i )
    {
        int x = dice();

        double divi = 10000000.0;

        double a = x / divi;
        double b = DecimalToDouble( x, 10000000 );

        if( (int)(a * divi) != x )
        {

            //std::cout << "ERROR AT A:" << x << '\t' << a << '\t' << b << std::endl;
            erra++;
        }

        if( (int)(b * divi) != x )
        {
            //std::cout << "ERROR AT B:" << x << '\t'  << a << '\t' << b << std::endl;
            errb++;
        }
    }

    std::cout.precision( 10 );
    std::cout << "A:" << (erra / (double)iterations) * 100.0 << "% B:"
            << (errb / (double)iterations) * 100.0 << "%" << std::endl;


    char stop;
    std::cin >> stop;
}

Win7x64 VS2010上的结果:A:6.4997%B:6.5188%

2 个答案:

答案 0 :(得分:3)

  

double res = myint / 1000000.0;

编译器的工作是将res设置为结果的最接近的可表示值。

答案 1 :(得分:1)

请注意,数值对您来说意味着什么,以及您在代码中使用的语言可用的表示形式之间总是存在差异。大多数情况下,它并不像在这种情况下那么明显。我想说的是:如果您的int值为12123456,那么这已经是实际值12.123456的表示。我可以想象将它转换为double的唯一原因是使用浮点算术(特别是除法),否则我会留在int

TL; DR:如果可能,我会尽量避免转换。如果你真的想这样做,imho log0的答案是完全有效的。