C++(标准库):09---分数运算(ratio库)

一、ratio概述

  • 自C++11起,C++标准库提供了一个接口允许你具体指定编译期分数,并允许对它们执行编译期运算
  • 以下摘自[N266:Chrnon]并略有改动:

二、ratio的实现

  • ratio由<ratio>提供,其定义如下:
    • type:产出相应类型,其也是一个ratio<>,其返回自身,可以直接使用域访问父访问
    • num:分子
    • den:分母,默认为1
  • 其所有成员都是public的
  • intmax_t是个带正负号的整数类型,其有能力表现出任何带正负号的整数,其被设计于<cstdint>或<stdint.h>内,至少具备64bit

演示案例

int main()
{
    typedef ratio<5, 3> FiveThirds;
    std::cout << FiveThirds::num << "/" << FiveThirds::den << std::endl;

    typedef ratio<25, 15> AlsoFiveThirds;
    std::cout << AlsoFiveThirds::num << "/" << AlsoFiveThirds::den << std::endl;

    typedef ratio<42,42> one;
    std::cout << one::num << "/" << one::den << std::endl;

    typedef ratio<0> zero;        //分母默认为1
    std::cout << zero::num << "/" << zero::den << std::endl;

    typedef ratio<7, -3> Neg1;    //-号会被移动到分子身上
    std::cout << Neg1::num << "/" << Neg1::den << std::endl;

    typedef ratio<-7, 3> Neg2;    //分子的-号保持不变
    std::cout << Neg2::num << "/" << Neg2::den << std::endl;

    typedef ratio<-7, -3> Neg3;   //分子分母的-号都会消失
    std::cout << Neg3::num << "/" << Neg3::den << std::endl;
}

三、ratio提供的操作

基本运算符

  • 分数的+、-、*、/分别被定义为ratio_add、ratio_substract、ratio_multiply、ratio_divide。它们的返回值也是一个ratio<>
  • 演示案例:
type返回的一个是ratio<>,2/7+2/6=13/21
typedef std::ratio_add<std::ratio<2, 7>, std::ratio<2, 6>>::type test;

std::cout << test::num << "/" << test::den << std::endl;

分数比较

std::cout << boolalpha;
std::cout << std::ratio_equal<std::ratio<1, 3>, std::ratio<1, 3>>::value << std::endl;
std::cout << std::ratio_equal<std::ratio<2, 3>, std::ratio<1, 3>>::value << std::endl;
std::cout << std::ratio_greater<std::ratio<2, 3>, std::ratio<1, 3>>::value << std::endl;

四、使用ratio的一些注意事项

  • 关于分母的一些注意事项:
    • ratio定义时,其分母不能定义为0,否则编译不通过
    • ratio定义时,如果不填分母,默认为1
  • 关于负号(-)的一些注意事项:
    • 如果分子无-号,分母有-号,分母的-号会被移动到分子身上
    • 如果分子有-号,分母无-号,则分子的-号保持不动
    • 如果分子分母都有-号,则-号都被消除
  • 分子可以为0
  • ratio会自动对分子和分母进行约分

演示案例

  • ratio会捕捉所有差错,例如分母为0、溢出等等。因此下面的无法编译通过
//无法编译通过,因为1/max乘以1/2会导致溢出,分母超过了其类型所能涵盖的极限
std::ratio_multiply<std::ratio<1, std::numeric_limits<long long>::max()>, std::ratio<1, 2>>::type;
  • 与上面同理,下面的表达式也无法通过编译,因为其除以了0:
typedef ratio<5, 3> FiveThirds;
typedef ratio<0> zero;          //分子为0,分母默认为1
std::ratio_divide<FiveThirds, zero>::type;
  • 但是下面的可以编译通过,因为下面只使用了ratio_divide<>,却没有实例化一个ratio<>对象,因此编译器检测不出来
typedef ratio<5, 3> FiveThirds;
typedef ratio<0> zero;
std::ratio_divide<FiveThirds, zero>; //只调用了ratio_divide,却没有实例化出任何ratio对象

五、预定义的ratio单位

  • ratio程序库预先定义好了很多ratio单位,可以直接使用。如下图所示:
    • 下图中的“optional”代表,只有“当它们可被intmax_t表达时”才被定义

  • 演示案例:
typedef std::ratio<1, 1000000000LL> test;
std::cout << test::num << "/" << test::den << std::endl;

typedef std::nano _nano;
std::cout << _nano::num << "/" << _nano::den << std::endl;

  • 这个演示案例也使得我们可以比较方便的指出纳秒(见下篇文章的Duration中的演示案例)
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

董哥的黑板报

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值