2005/12/20

boost::rational

boost::rational 是一个类似 std::complex 的 class template 。它提供了对分数的支持。它需要一个 template type parameter ,称作 underlying integer type 。 C++ 的任意 built-in integer types 都可以在这里使用;用户自定义的 integer type 也可以使用,但是必须是下面 concepts 的 model :
  • Assignable
  • Default Constructible
  • Equality Comparable
  • LessThan Comparable

而且, I 必须是一个 integer-like 型别。就是说,对于型别 I 的任意两个值 n and m ,下面的表达式必须合法,并且拥有“符合期望”的语义。

  • n + m
  • n - m
  • n * m
  • n / m (must truncate, and n/m must be positive if n and m are positive)
  • n % m (n%m must be positive if n and m are positive)
  • Assignment versions of the above
  • +n, -n

此型别中必须存在值 01 。并且能通过 I(0)I(1) 生成。(不过并不需要从整数到 I 的隐式转换,这里只需要用到 explicit constructor 。)

可以令 I 是一个 unsigned type ,这样派生出来的 rational class 也是 unsigned 。减法的结果将总是一个非负数,这时发生的 underflow behaviour 将是不确定的。

  • rational_cast(rational) 依赖于从 I 到 T 的 static_cast ,并且对型别 T 的任意两个值 x and y ,表达式 x/y 都合法。
  • 输入输出 operators 依赖于型别 I 对应的输入输出 operators 。

Utility Functions

下面两个函数用来计算给定两个数的最大公约数和最小公倍数,可以工作的型别必须已经定义这些 operations: =, +=, *=, /=, %, <>

gcd(n, m) The greatest common divisor of n and m
lcm(n, m) The least common multiple of n and m

在 boost::math 中也有同样功能的两个函数。不过这两对分别在不同的 namespace 中。

Constructors

Rationals 可以用一对 integers (numerator, denominator) 或者一个 integer 构造。还有一个 default constructor ,将 rational 初始化为 0 。

    I n, d;
   rational zero;
   rational r1(n);
   rational r2(n, d);

单参数的 constructor 没有被声明成 explicit ,因此可以进行从 underlying integer type 到 rational type 的隐式转换。

算术运算

rational class 支持所有的标准算术运算。

    +    +=
   -    -=
   *    *=
   /    /=
   ++   --    (both prefix and postfix)
   ==   !=
   <    >
   <=   >=

Input and Output

rational 的 external representation 是用一个 slash (/) 分开的两个 integer 。输入 rational 时,格式必须是一个 integer 后边紧跟一个 slash (不能有 whitespace ),再紧跟另一个 integer 。一个 integer 的 external representation 由 underlying integer type 。

In-place assignment

对任意的 rational rr.assign(n, m) 提供了一个相对于 r = rational(n, m); 更快速的等价表示,它不会生成中间变量。虽然这对于基于 machine integer types 的 rationals 是没有必要的,但是对于基于 unlimited-precision integers 的 rationals ,它可以减少开销。

Conversions

不存在从 rationals 到其它任何型别的隐式转换。然而,存在一个显式转换函数, rational_cast(r) 。可以这样使用:

    rational r(22,7);
   double nearly_pi = boost::rational_cast(r);

如果要转换的 rational 的 numerator 和 denominator 不能安全的 cast 到某种 floating point type ,或者 numerator 与 denominator 的除法不能正确计算(在要转换到的目标 floating point type 中)。

Numerator and Denominator

可以通过两个 member functions numerator() and denominator() 来访问 rational 的 internal representation

Exceptions

rational 的 denominator 不能是 0 (这个 lib 并不支持 infinity or NaN 这样的 represention )。一旦出现一个 denominator 是 0 的 rational ,将抛出 boost::bad_rational 异常。这只应该出现在当用户尝试显式构造一个 denominator 为 0 的 rational ,或者用 0 去除一个 rational 的情况下。

Internal representation

注意:这里讲述的是实现细节,不要依赖这里的信息编程。

在内部, rational 被保存为 a pair (numerator, denominator) of integers (它们的型别就是 rational 的 template type parameter )。 rationals 总是保存为最简分数的形式( gcd(numerator, denominator) = 1 ,并且 denominator 总是正数)。

没有评论: