This subclause describes the ratio library. It provides a class template ratio which exactly represents any finite rational number with a numerator and denominator representable by compile-time constants of type intmax_t.
Throughout this subclause, the names of template parameters are used to express type requirements. If a template parameter is named R1 or R2, and the template argument is not a specialization of the ratio template, the program is ill-formed.
namespace std // [ratio.ratio], class template ratio template <intmax_t N, intmax_t D = 1> class ratio; // [ratio.arithmetic], ratio arithmetic template <class R1, class R2> using ratio_add = @see below@; template <class R1, class R2> using ratio_subtract = @see below@; template <class R1, class R2> using ratio_multiply = @see below@; template <class R1, class R2> using ratio_divide = @see below@; // [ratio.comparison], ratio comparison template <class R1, class R2> struct ratio_equal; template <class R1, class R2> struct ratio_not_equal; template <class R1, class R2> struct ratio_less; template <class R1, class R2> struct ratio_less_equal; template <class R1, class R2> struct ratio_greater; template <class R1, class R2> struct ratio_greater_equal; // [ratio.si], convenience SI typedefs typedef ratio<1, 1'000'000'000'000'000'000'000'000> yocto; // see below typedef ratio<1, 1'000'000'000'000'000'000'000> zepto; // see below typedef ratio<1, 1'000'000'000'000'000'000> atto; typedef ratio<1, 1'000'000'000'000'000> femto; typedef ratio<1, 1'000'000'000'000> pico; typedef ratio<1, 1'000'000'000> nano; typedef ratio<1, 1'000'000> micro; typedef ratio<1, 1'000> milli; typedef ratio<1, 100> centi; typedef ratio<1, 10> deci; typedef ratio< 10, 1> deca; typedef ratio< 100, 1> hecto; typedef ratio< 1'000, 1> kilo; typedef ratio< 1'000'000, 1> mega; typedef ratio< 1'000'000'000, 1> giga; typedef ratio< 1'000'000'000'000, 1> tera; typedef ratio< 1'000'000'000'000'000, 1> peta; typedef ratio< 1'000'000'000'000'000'000, 1> exa; typedef ratio< 1'000'000'000'000'000'000'000, 1> zetta; // see below typedef ratio<1'000'000'000'000'000'000'000'000, 1> yotta; // see below
namespace std { template <intmax_t N, intmax_t D = 1> class ratio { public: static constexpr intmax_t num; static constexpr intmax_t den; typedef ratio<num, den> type; }; }
If the template argument D is zero or the absolute values of either of the template arguments N and D is not representable by type intmax_t, the program is ill-formed. [ Note: These rules ensure that infinite ratios are avoided and that for any negative input, there exists a representable value of its absolute value which is positive. In a two's complement representation, this excludes the most negative value. — end note ]
Each of the alias templates ratio_add, ratio_subtract, ratio_multiply, and ratio_divide denotes the result of an arithmetic computation on two ratios R1 and R2. With X and Y computed (in the absence of arithmetic overflow) as specified by Table [tab:ratio.arithmetic], each alias denotes a ratio<U, V> such that U is the same as ratio<X, Y>::num and V is the same as ratio<X, Y>::den.
If it is not possible to represent U or V with intmax_t, the program is ill-formed. Otherwise, an implementation should yield correct values of U and V. If it is not possible to represent X or Y with intmax_t, the program is ill-formed unless the implementation yields correct values of U and V.
Type | Value of X | Value of Y |
ratio_add<R1, R2> | R1::num * R2::den + | R1::den * R2::den |
R2::num * R1::den | ||
ratio_subtract<R1, R2> | R1::num * R2::den - | R1::den * R2::den |
R2::num * R1::den | ||
ratio_multiply<R1, R2> | R1::num * R2::num | R1::den * R2::den |
ratio_divide<R1, R2> | R1::num * R2::den | R1::den * R2::num |
[ Example:
static_assert(ratio_add<ratio<1,3>, ratio<1,6>>::num == 1, "1/3+1/6 == 1/2");
static_assert(ratio_add<ratio<1,3>, ratio<1,6>>::den == 2, "1/3+1/6 == 1/2");
static_assert(ratio_multiply<ratio<1,3>, ratio<3,2>>::num == 1, "1/3*3/2 == 1/2");
static_assert(ratio_multiply<ratio<1,3>, ratio<3,2>>::den == 2, "1/3*3/2 == 1/2");
// The following cases may cause the program to be ill-formed under some implementations
static_assert(ratio_add<ratio<1,INT_MAX>, ratio<1,INT_MAX>>::num == 2,
"1/MAX+1/MAX == 2/MAX");
static_assert(ratio_add<ratio<1,INT_MAX>, ratio<1,INT_MAX>>::den == INT_MAX,
"1/MAX+1/MAX == 2/MAX");
static_assert(ratio_multiply<ratio<1,INT_MAX>, ratio<INT_MAX,2>>::num == 1,
"1/MAX * MAX/2 == 1/2");
static_assert(ratio_multiply<ratio<1,INT_MAX>, ratio<INT_MAX,2>>::den == 2,
"1/MAX * MAX/2 == 1/2");
— end example ]
template <class R1, class R2> struct ratio_equal
: integral_constant<bool, see below> { };
If R1::num == R2::num and R1::den == R2::den, ratio_equal<R1,
R2> shall be derived from
integral_constant<bool, true>; otherwise it shall
be derived from integral_constant<bool, false>.
template <class R1, class R2> struct ratio_not_equal
: integral_constant<bool, !ratio_equal<R1, R2>::value> { };
template <class R1, class R2> struct ratio_less
: integral_constant<bool, see below> { };
If R1::num * R2::den < R2::num * R1::den, ratio_less<R1, R2> shall be derived from integral_constant<bool, true>; otherwise it shall be derived from integral_constant<bool, false>. Implementations may use other algorithms to compute this relationship to avoid overflow. If overflow occurs, the program is ill-formed.
template <class R1, class R2> struct ratio_less_equal
: integral_constant<bool, !ratio_less<R2, R1>::value> { };
template <class R1, class R2> struct ratio_greater
: integral_constant<bool, ratio_less<R2, R1>::value> { };
template <class R1, class R2> struct ratio_greater_equal
: integral_constant<bool, !ratio_less<R1, R2>::value> { };
For each of the typedefs yocto, zepto, zetta, and yotta, if both of the constants used in its specification are representable by intmax_t, the typedef shall be defined; if either of the constants is not representable by intmax_t, the typedef shall not be defined.