20 General utilities library [utilities]

20.10 Compile-time rational arithmetic [ratio]

20.10.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, if the template argument types R1 and R2 are not specializations of the ratio template, the program is ill-formed.

20.10.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, 1000000000000000000000000> yocto;  // see below
  typedef ratio<1,    1000000000000000000000> zepto;  // see below
  typedef ratio<1,       1000000000000000000> atto;
  typedef ratio<1,          1000000000000000> femto;
  typedef ratio<1,             1000000000000> pico;
  typedef ratio<1,                1000000000> nano;
  typedef ratio<1,                   1000000> micro;
  typedef ratio<1,                      1000> milli;
  typedef ratio<1,                       100> centi;
  typedef ratio<1,                        10> deci;
  typedef ratio<                       10, 1> deca;
  typedef ratio<                      100, 1> hecto;
  typedef ratio<                     1000, 1> kilo;
  typedef ratio<                  1000000, 1> mega;
  typedef ratio<               1000000000, 1> giga;
  typedef ratio<            1000000000000, 1> tera;
  typedef ratio<         1000000000000000, 1> peta;
  typedef ratio<      1000000000000000000, 1> exa;
  typedef ratio<   1000000000000000000000, 1> zetta;  // see below
  typedef ratio<1000000000000000000000000, 1> yotta;  // see below
}

20.10.3 Class template ratio [ratio.ratio]

namespace std {
  template <intmax_t N, intmax_t D = 1>
  class ratio {
  public:
    typedef ratio<num, den> type;
    static constexpr intmax_t num;
    static constexpr intmax_t den;
  };
}

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.10.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.10.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.10.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.