Numeric Cast from integer to floating point

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 <boost/numeric/conversion/cast.hpp> 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? Thanks in advance

Changed subject to see if it gets any attention... <dariomt <at> gmail.com> writes:
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.
std::numeric_limits<double>::max() ) << std::endl;
i=123445678911188878d=123445678911188880.000000next=123445678911188896.00000 0prev=123445678911188864.000000dd=123445678911188880.000000because that integer cannot be represented in double precisionIs there something in Boost to help here?Thanks in advance

2014-09-08 17:53 GMT+04:00 <dariomt@gmail.com>:
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<result_type>(s) ; if (std::abs(s - res) >= 1) { throw std::runtime_error("precision loss"); } return res; }} ; template <typename Target, typename Source> inline Target precise_numeric_cast( Source arg ) // use this instead of numeric_cast { typedef numeric::conversion_traits<Target, Source> conv_traits; typedef numeric::numeric_cast_traits<Target, Source> cast_traits; typedef boost::numeric::converter < Target, Source, conv_traits, typename cast_traits::overflow_policy, typename cast_traits::rounding_policy, /* only the following line differs from the original numeric_cast*/ precise_converter< conv_traits >, typename cast_traits::range_checking_policy > converter; return converter::convert(arg); } -- Best regards, Antony Polukhin

[Please do not mail me a copy of your followup] Antony Polukhin <antoshkka@gmail.com> spake the secret code <CAKqmYPa8aHVeYYB7ZwyLTO7twjnJ_XoohcZ3TXC4eng9pkQ=uA@mail.gmail.com> thusly:
Robert Ramey's "Safe Numerics" is designed to allow the cast to proceed when no precision is lost and do something else when precision is lost. <http://rrsd.com/blincubator.com/bi_library/safe-numerics/?gform_post_id=426> -- "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline> The Computer Graphics Museum <http://computergraphicsmuseum.org> The Terminals Wiki <http://terminals.classiccmp.org> Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

From: Boost-users [mailto:boost-users-bounces@lists.boost.org] On Behalf Of dariomt@gmail.com Sent: 08 September 2014 14:54 To: boost-users@lists.boost.org Subject: [Boost-users] Numeric Cast from integer to floating point 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 <boost/numeric/conversion/cast.hpp> 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? Would using 128-bit floating point help? http://www.boost.org/doc/libs/1_54_0/libs/multiprecision/doc/html/boost_mult... (though of course, the biggest 128-bit int cannot be represented in 128-bit FP.) Paul --- Paul A. Bristow Prizet Farmhouse Kendal UK LA8 8AB +44 (0) 1539 561830
participants (5)
-
Antony Polukhin
-
dariomt
-
dariomt@gmail.com
-
legalize+jeeves@mail.xmission.com
-
Paul A. Bristow