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;
template <class R1, class R2>
inline constexpr bool ratio_equal_v = ratio_equal<R1, R2>::value;
template <class R1, class R2>
inline constexpr bool ratio_not_equal_v = ratio_not_equal<R1, R2>::value;
template <class R1, class R2>
inline constexpr bool ratio_less_v = ratio_less<R1, R2>::value;
template <class R1, class R2>
inline constexpr bool ratio_less_equal_v = ratio_less_equal<R1, R2>::value;
template <class R1, class R2>
inline constexpr bool ratio_greater_v = ratio_greater<R1, R2>::value;
template <class R1, class R2>
inline constexpr bool ratio_greater_equal_v = ratio_greater_equal<R1, R2>::value;
// [ratio.si], convenience SI typedefs
using yocto = ratio<1, 1'000'000'000'000'000'000'000'000>; // see below
using zepto = ratio<1, 1'000'000'000'000'000'000'000>; // see below
using atto = ratio<1, 1'000'000'000'000'000'000>;
using femto = ratio<1, 1'000'000'000'000'000>;
using pico = ratio<1, 1'000'000'000'000>;
using nano = ratio<1, 1'000'000'000>;
using micro = ratio<1, 1'000'000>;
using milli = ratio<1, 1'000>;
using centi = ratio<1, 100>;
using deci = ratio<1, 10>;
using deca = ratio< 10, 1>;
using hecto = ratio< 100, 1>;
using kilo = ratio< 1'000, 1>;
using mega = ratio< 1'000'000, 1>;
using giga = ratio< 1'000'000'000, 1>;
using tera = ratio< 1'000'000'000'000, 1>;
using peta = ratio< 1'000'000'000'000'000, 1>;
using exa = ratio< 1'000'000'000'000'000'000, 1>;
using zetta = ratio< 1'000'000'000'000'000'000'000, 1>; // see below
using yotta = ratio<1'000'000'000'000'000'000'000'000, 1>; // 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;
using type = ratio<num, 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 ]
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 51, 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 : bool_constant<R1::num == R2::num && R1::den == R2::den> { };
template <class R1, class R2>
struct ratio_not_equal : bool_constant<!ratio_equal_v<R1, R2>> { };
template <class R1, class R2>
struct ratio_less : bool_constant<see below> { };
If R1::num × R2::den is less than R2::num × R1::den, ratio_less<R1, R2> shall be derived from bool_constant<true>; otherwise it shall be derived from bool_constant<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 : bool_constant<!ratio_less_v<R2, R1>> { };
template <class R1, class R2>
struct ratio_greater : bool_constant<ratio_less_v<R2, R1>> { };
template <class R1, class R2>
struct ratio_greater_equal : bool_constant<!ratio_less_v<R1, R2>> { };
For each of the typedef-names 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.