Reputation: 1107
What is the correct way to convert an int with representing a decimal to a double?
I have an int representing for example 12,123456 as 12123456. This comes from a network device that I cannot change.
I want to convert it to double with minimal error.
The naive solution would be:
double res = boost::numeric_cast<double>(myint) / 1000000.0;
I think that converting myint(a huge number) to a double is more lossy than some other method because the resulting value is near 1 where dobule has more precision.
I am looking for what the least lossy method of doing this conversion is.
EDIT:
I didn't believe log0's answer was right. TL;DR He is.
The test I used:
#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;
}
Result on Win7x64 VS2010: A:6.4997% B:6.5188%
Upvotes: 1
Views: 127
Reputation: 123440
Note that there is always a difference between what a numerical value means for you and what representation available from the language you use in your code. Most of the time it is just not as obvious as in this case. What I want to say is: If you have an int
whose value is 12123456
then this is already a representation of the actual value 12.123456
. The only reason I could imagine to convert it to a double
is to use floating point arithmetics (especially division) otherwise I would just stay with the int
.
TL;DR: If possible I would try to avoid the conversion. If you really want to do it, imho log0's answer is perfectly valid.
Upvotes: 1
Reputation: 10947
double res = myint / 1000000.0;
That's the job of the compiler to set res to the closest representable value of the result.
Upvotes: 3