20 General utilities library [utilities]

20.11 Compile-time rational arithmetic [ratio]

20.11.1 In general [ratio.general]

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.

20.11.2 Header <ratio> synopsis [ratio.syn]

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

20.11.3 Class template ratio [ratio.ratio]

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 ]

The static data members num and den shall have the following values, where gcd represents the greatest common divisor of the absolute values of N and D:

  • num shall have the value sign(N) * sign(D) * abs(N) / gcd.

  • den shall have the value abs(D) / gcd.

20.11.4 Arithmetic on ratios [ratio.arithmetic]

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.

Table 58 — Expressions used to perform ratio arithmetic
TypeValue of XValue 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 ]

20.11.5 Comparison of ratios [ratio.comparison]

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> { };

20.11.6 SI types for ratio [ratio.si]

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.