Boost logo

Boost Users :

Subject: [Boost-users] [numeric conversation] behavior on std::numeric_limits<double>::max() + eps with numeric_cast
From: Olaf Peter (ope-devel_at_[hidden])
Date: 2014-06-09 02:53:32


Hello,

at this time I play with numeric_cast and struggle with this:

first:
             double z = std::numeric_limits<double>::max();
             z += 2*std::numeric_limits<double>::epsilon(); // doesn't
matter if 1*eps
             std::cout << z << std::endl;
             std::cout << boost::numeric_cast<double>(z) << '\n';

I would expect that an exception is thrown which isn't, the output is
1.79769e+308
1.79769e+308

and as second: If I write my onw UDT as shown in the tutorial like:

namespace my {

     enum range_check_result
     {
         cNonFinite = 0,
         cInRange = 1,
         cNegOverflow = 2,
         cPosOverflow = 3
     } ;

     //! Define a custom range checker
     template<typename Traits, typename OverFlowHandler>
     struct range_checker
     {
         typedef typename Traits::argument_type argument_type;
         typedef typename Traits::source_type S;
         typedef typename Traits::target_type T;

         //! Check range of integral types.
         static range_check_result out_of_range(argument_type value)
         {
             if(!std::isfinite(value.to_builtin())) // Neither infinity
nor NaN.
                 return cNonFinite;
             else if(value > boost::numeric::bounds<T>::highest())
                 return cPosOverflow;
             else if(value < boost::numeric::bounds<T>::lowest())
                 return cNegOverflow;
             else
                 return cInRange;
         }

         static void validate_range(argument_type value)
         {
BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_bounded);
             OverFlowHandler()(out_of_range(value));
         }
     };
    ....
     struct bad_numeric_cast : virtual boost::exception, virtual
std::bad_cast
     { ... };

     struct rounding_error : virtual boost::exception, std::domain_error
     {
         rounding_error() : std::domain_error("NaN or Infinity") {} //
XXX Better solution?

         virtual const char * what() const throw() {
             return "bad numeric conversion: can not be represented in
the target integer type";
         }
     };

     struct negative_overflow : virtual bad_numeric_cast
     { .... };

     struct positive_overflow : virtual bad_numeric_cast
     { .... };

     struct overflow_handler
     {
         void operator()(range_check_result result)
         {
             if(result == cNonFinite)
                 BOOST_THROW_EXCEPTION(rounding_error());
             else if(result == cNegOverflow)
                 BOOST_THROW_EXCEPTION(negative_overflow());
             else if(result == cPosOverflow)
                 BOOST_THROW_EXCEPTION(positive_overflow());
         }
     };

it doesn't change the result - is this the right way?

Thanks,
Olaf


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net