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.
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=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>:
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?
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:
2014-09-08 17:53 GMT+04:00 <dariomt@gmail.com>:
[...] 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.
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