23 General utilities library [utilities]

23.16 Compile-time rational arithmetic [ratio]

23.16.4 Arithmetic on ratios [ratio.arithmetic]

Каждый из шаблонов псевдонимов ratio_­add, ratio_­subtract, ratio_­multiplyи ratio_­divide обозначает результат арифметического вычисления на два ratioсекунд R1 и R2. При вычислении X и Y вычислении (при отсутствии арифметического переполнения), как указано в таблице 51, каждый псевдоним обозначает ratio<U, V> такой U же, как ratio<X, Y>​::​num и V такой же, как ratio<X, Y>​::​den.

Если это не возможно представить U или V с intmax_­t, программа плохо сформирована. В противном случае реализация должна давать правильные значения U и V. Если невозможно представить X или Y с intmax_­t, программа плохо сформирована, если реализация не дает правильных значений U и V.

Таблица 51 - Выражения, используемые для выполнения арифметики отношений
ТипЗначение XЗначение 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]