2014-09-08 17:53 GMT+04:00
Hi,
Quoting the docs for boost::numeric_cast: "There are several situations where conversions are unsafe: [...] Conversions from floating point types to integral types."
What about conversions from integral types to floating point types? E.g. from 64bit int to double.
The following example shows what I mean:
#include <iostream> #include <cmath> #include
int main() { const uint64_t i = 123445678911188878; std::cout << "i=" << i << std::endl;
const double d = i; std::cout << "d=" << std::fixed << d << std::endl; std::cout << "next=" << std::fixed << std::nextafter(d, std::numeric_limits<double>::max() ) << std::endl; std::cout << "prev=" << std::fixed << std::nextafter(d, -std::numeric_limits<double>::max()) << std::endl;
// I'd expect the following cast to fail const double dd = boost::numeric_cast<double>(i); std::cout <<"dd=" << std::fixed << dd << std::endl;
return 0; }
prints
i=123445678911188878
d=123445678911188880.000000
next=123445678911188896.000000
prev=123445678911188864.000000
dd=123445678911188880.000000
because that integer cannot be represented in double precision
Is there something in Boost to help here?
That's an interesting question. numeric_cast function was designed to
detect positive and negative overflows, not precision loss. Consider the
example:
std::cout << boost::numeric_cast<int>(1.1999); // OK: 1
std::cout << boost::numeric_cast<int>(1e100); // exception: positive
overflow
Your example is related to the first line, where 1.1999 is converted to
int. When uint64_t i = 123445678911188878; is converted to double there is
no positive/negative overflow, there's only a precision loss.
There is no out-of-the-box solution for your problem, but you can try to so
something by your own using the numeric converter (code was not tested):
// See:
http://www.boost.org/doc/libs/1_56_0/libs/numeric/conversion/doc/html/boost_...
template<class Traits> struct precise_converter { typedef typename Traits
::result_type result_type ; typedef typename Traits::argument_type
argument_type ;
static result_type low_level_convert ( argument_type s ) {
const result_type res = static_cast