Search code examples
c++boostfloor

C++ boost rational class, floor function


I'm new to using boost.

Besides simply doing x.numerator()/x.denominator, is there a proper 'boost-type' way of invoking the floor(x) function (i.e. truncation towards zero) when using the boost rational library?

Thanks


Solution

  • There isn't. I've looked closely at it, and the only function that even deals with conversion to a continued-fraction representation starts of with the exact same operation (formatted for legibility):

    struct {
        Rat::int_type n, d, q, r;
    } ts = {
        l.numerator(), l.denominator(),
        static_cast<Rat::int_type>(l.numerator() / l.denominator()), static_cast<Rat::int_type>(l.numerator() % l.denominator()) 
    },
      rs = {
          r.numerator(), r.denominator(),
          static_cast<Rat::int_type>(r.numerator() / r.denominator()), static_cast<Rat::int_type>(r.numerator() % r.denominator()) 
    };
    

    While this might slightly disappoint you, it does validate your approach, which is good.

    If you want you can provide your own floor overload to be found via ADL ¹

    Here's my generalist suggestion, assuming you're injecting it into namespace boost:

    namespace boost {
        template <typename IntType>
        constexpr IntType floor(rational<IntType> const& r) {
            return static_cast<IntType>(r.numerator() / r.denominator());
        }
    }
    

    Live Demo

    Live On Coliru

    #include <boost/rational.hpp>
    
    namespace boost {
        template <typename IntType>
        constexpr IntType floor(rational<IntType> const& r) {
            return static_cast<IntType>(r.numerator() / r.denominator());
        }
    }
    
    #include <iostream>
    
    template <typename IntType> void test()
    {
        boost::rational<IntType> a(230,7), b(222*111111,-777777);
    
        std::cout << "a: " << a << " -> " << floor(a) << "\n";
        std::cout << "b: " << b << " -> " << floor(b) << "\n";
    }
    
    #include <boost/multiprecision/cpp_int.hpp>
    int main() {
        test<int>();
        test<boost::multiprecision::cpp_int>();
    }
    

    Prints

    a: 230/7 -> 32
    b: -222/7 -> -31
    a: 230/7 -> 32
    b: -222/7 -> -31
    

    ¹ declare it in the namespace declaring your integer type, or inside namespace ::boost in order to let it kick in.