The class template std::ratio
provides compile-time rational arithmetic support. Each instantiation of this template exactly represents any finite rational number as long as its numerator Num and denominator Denom are representable as compile-time constants of type std::intmax_t
. In addition, Denom may not be zero and both Num and Denom may not be equal to the most negative value.
有理数基本用法示例:
cpp
#include <iostream>
#include <ratio>
#include <format>
#include <typeinfo>
void test_01(){
using r1 = std::ratio<1,60>; // 与std::ratio<2,120>是不同的类型
std::cout << typeid(r1).name() << std::endl; // St5ratioILl1ELl60EE
std::intmax_t num{r1::num};
std::intmax_t den{r1::den};
std::cout << std::format("num={}, den={}\n", num, den); // num=1, den=60
std::intmax_t n{1};
std::intmax_t d{60};
// 要求Num和Denom均是编译期常量
//using r2 = std::ratio<n,d>; // the value of 'n' is not usable in a constant expression
// the value of 'n' is not usable in a constant expression
}
int main() {
test_01();
}
有理数加法运算示例:
cpp
#include <iostream>
#include <ratio>
#include <format>
void test_02(){
using r1 = std::ratio<1,6>;
using r2 = std::ratio<1,3>;
using radd = std::ratio_add<r1, r2>;
std::cout << std::format("{0}/{1}+{2}/{3}={4}/{5}\n",
r1::num, r1::den, r2::num, r2::den, radd::num, radd::den); // 1/6+1/3=1/2
using rsub = std::ratio_subtract<r1, r2>;
std::cout << std::format("{0}/{1}-{2}/{3}={4}/{5}\n",
r1::num, r1::den, r2::num, r2::den, rsub::num, rsub::den); // 1/6-1/3=-1/6
using rmultiply = std::ratio_multiply<r1, r2>;
std::cout << std::format("{0}/{1}*{2}/{3}={4}/{5}\n",
r1::num, r1::den, r2::num, r2::den, rmultiply::num, rmultiply::den); // 1/6*1/3=1/18
using rdivide = std::ratio_divide<r1, r2>;
std::cout << std::format("{0}/{1}➗{2}/{3}={4}/{5}\n",
r1::num, r1::den, r2::num, r2::den, rdivide::num, rdivide::den); // 1/6➗1/3=1/2
}
int main() {
test_02();
}
有理数比较运算示例:
cpp
#include <iostream>
#include <ratio>
#include <format>
void test_03(){
constexpr bool equ = std::ratio_equal_v<std::ratio<2,3>, std::ratio<4,6>>;
static_assert(equ == true);
std::cout << "2/3 " << (equ ? "==" : "!=") << " 4/6\n"; // 2/3 == 4/6
using r1 = std::ratio<1,6>;
using r2 = std::ratio<2,12>;
std::cout << std::format("{}/{}\n", r1::num, r1::den); // 1/6
std::cout << std::format("{}/{}\n", r2::num, r2::den); // 1/6
constexpr bool r3 = std::ratio_equal<r1, r2>::value;
std::cout << std::format("{}/{}{}{}/{}\n",
r1::num, r1::den, r3?"==":"!=",r2::num, r2::den); // 1/6==1/6
using r4 = std::ratio_less<r1,r2>;
std::cout << r4::value << std::endl; // 0
using r5 = std::milli;
std::cout << std::format("{}/{}\n", r5::num, r5::den); // 1/1000
using r6 = std::mega;
std::cout << std::format("{}/{}\n", r6::num, r6::den); // 1000000/1
}
int main() {
test_03();
}