std::ratio详解


std::ratio是什么?

std::ratio代表一个比例,或者说比率。其实就是将给定的两个整数分别除以它们的最大公约数得到一个分数(分子及分母)。其定义为(vs2015):

template<intmax_t _Nx, intmax_t _Dx = 1>
struct ratio
{    // holds the ratio of _Nx to _Dx
    static_assert(_Dx != 0, "zero denominator");
    static_assert(-INTMAX_MAX <= _Nx, "numerator too negative");
    static_assert(-INTMAX_MAX <= _Dx, "denominator too negative");
 
    static constexpr intmax_t num = _Sign_of<_Nx>::value
        * _Sign_of<_Dx>::value * _Abs<_Nx>::value / _Gcd<_Nx, _Dx>::value;
 
    static constexpr intmax_t den = _Abs<_Dx>::value / _Gcd<_Nx, _Dx>
        ::value;
 
    typedef ratio<num, den> type;
};

附加部分类型以及宏的定义:

typedef long long          intmax_t;
#define INTMAX_MAX       INT64_MAX

std::ratio具有2个intmax_t的非类型模板参数,_Nx代表分子(numerator),_Dx代表分母(denominator)。_Dx不可以为0,_Nx_Dx都不可以小于-INTMAX_MAX

numden分别代表_Nx_Dx除以它们的最大公约数得到的商。

类型type代表换算后的ratio类型。因此ratio<1,2>::type、ratio<4,8>::type、ratio<3,6>::type都是相同的类型。

STL还定义了一些类型(vs2013):

typedef ratio<1, 1000000000000000000LL> atto;
typedef ratio<1, 1000000000000000LL> femto;
typedef ratio<1, 1000000000000LL> 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<1000000000000LL, 1> tera;
typedef ratio<1000000000000000LL, 1> peta;
typedef ratio<1000000000000000000LL, 1> exa;

示例代码:

template<typename T>
void output(const T &t)
{
	cout << typeid(t).name() << ":" << endl;
	cout << "num:" << t.num << endl;
	cout << "den:" << t.den << endl;
}
 
void call_by_main()
{
	ratio<2, 4> r;
	output(r);
	ratio<1, 3> r1;
	output(r1);
	ratio<3, 6> r3;
	output(r3);
 
	system("pause");
}

输出为:

struct std::ratio<2,4>:
num:1
den:2
struct std::ratio<1,3>:
num:1
den:3
struct std::ratio<3,6>:
num:1
den:2
请按任意键继续. . .

STL还定义了一些辅助运算用的模板类。
其中一些以类型的方式提供了2个ratio类型的各种算数运算结果。注意,是类型的运算,得到的结果当然也是类型,通常为x::type的形式。

另外一些以值的方式提供了2个ratio类型的关系运算结果,这个结果是值,通常为x::value的形式。

这些类型有:

名称type 值
ratio_addR1 + R2
ratio_divideR1 / R2
ratio_equalR1 == R2
ratio_greaterR1 > R2
ratio_greater_equalR1 >= R2
ratio_lessR1 < R2
ratio_less_equalR1 <= R2
ratio_multiplyR1 * R2
ratio_not_equal!(R1 == R2)
ratio_subtractR1 - R2

以std::ratio_add来说,它的作用是求出两个ratio类型的和的类型, 它的定义如下:

template<class _R1,
	class _R2>
	struct _Ratio_add
	{	// add two ratios
	static_assert(_Are_ratios<_R1, _R2>::value,
		"ratio_add<R1, R2> requires R1 and R2 to be ratio<>s.");
 
	static constexpr intmax_t _N1 = _R1::num;
	static constexpr intmax_t _D1 = _R1::den;
	static constexpr intmax_t _N2 = _R2::num;
	static constexpr intmax_t _D2 = _R2::den;
 
	static constexpr intmax_t _Gx = _Gcd<_D1, _D2>::value;
 
	// typename ratio<>::type is necessary here
	typedef typename ratio<
		_Safe_add<
			_Safe_mult<_N1, _D2 / _Gx>::value,
			_Safe_mult<_N2, _D1 / _Gx>::value
			>::value,
		_Safe_mult<_D1, _D2 / _Gx>::value
		>::type type;
	};
 
template<class _R1,
	class _R2>
	using ratio_add = typename _Ratio_add<_R1, _R2>::type;

使用示例:

template<typename T>
void output(const T &t)
{
    cout << typeid(t).name() << ":" << endl;
    cout << "num:" << t.num << endl;
    cout << "den:" << t.den << endl;
}
 
void call_by_main()
{
    ratio<2, 4> r;
    output(r);
    ratio<1, 3> r1;
    output(r1);
    //求和的类型:
    ratio_add<decltype(r), decltype(r1)> sum;
    output(sum);
    //第一个类型是否大于第二个类型:
    using gr = ratio_greater<decltype(r), decltype(r1)>;
    cout << "gr::value_type:" << typeid(gr::value_type).name() << endl;
    cout << "gr::value:" << gr::value << endl;
 
    system("pause");
}

输出为:

struct std::ratio<2,4>:
num:1
den:2
struct std::ratio<1,3>:
num:1
den:3
struct std::ratio<5,6>:
num:5
den:6
gr::value_type:bool
gr::value:1
请按任意键继续. . .
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值