3.4 处理特殊情况的过程
在上面的最后版本里用到下面运算:
n / I(2)
n % I(2) == I(0)
n % I(2) != I(0)
n == I(0)
n == I(1)
其中/和%的代价很高.对无符号整数或有符号整数的非负值,可以用移位和掩码运算来代替它们.
识别出程序里经常出现的表达式,其中涉及一些过程或某种类型的常量.将它们定义为相应的特殊情况过程常常很有价值.针对特殊情况的实现经常比一般情况的处理更高效,因此应该把这类过程放入类型的计算基.对语言的内部类型,通常存在针对特殊情况的机器指令.对用户定义类型,针对特殊情况的优化也常有显著效果.举例说,两个任意多项式的除法比一个多项式除以x难得多.与此类似,两个高斯整数(形式为a+bi的数,其中a和b都是整数而i=√.1)相除比一个高斯整数除以1+i难得多.
任何整数类型都应该提供下面的特殊情况过程:
练习3.2请为C++的各整数类型实现上面这些过程.
现在可以给出求幂过程的最后实现了,其中用到一些特殊情况过程:
template<typename I, typename Op>
requires(Integer(I) && BinaryOperation(Op))
Domain(Op) power accumulate positive(Domain(Op) r,
Domain(Op) a, I n,
Op op)
{
//前条件:associative(op)∧positive(n)
while (true) {
if (odd(n)) {
r = op(r, a);
if (one(n)) return r;
}
a = op(a, a);
n = half nonnegative(n);
} }
template<typename I, typename Op> requires(Integer(I) && BinaryOperation(Op)) Domain(Op) power accumulate(Domain(Op) r, Domain(Op) a, I n, Op op)
{
//前条件:associative(op)∧.negative(n)
if (zero(n)) return r;
return power accumulate positive(r, a, n, op); }
template<typename I, typename Op>
requires(Integer(I) && BinaryOperation(Op)) Domain(Op) power(Domain(Op) a, I n, Op op) {
//前条件:associative(op)∧positive(n)
while (even(n)) {a = op(a, a);n = half nonnegative(n);
}
n = half nonnegative(n);
if (zero(n)) return a;
return power accumulate positive(a, op(a, a), n, op); }
由于已知a n+m = a n a m , 表达式a 0 必须求出运算op的单位元.可以把单位元作为操作的另一参数传入,将power的定义扩充到包括0次幂:6
template<typename I, typename Op>
requires(Integer(I) && BinaryOperation(Op))
Domain(Op) power(Domain(Op) a, I n, Op op, Domain(Op) id)
{
//前条件:associative(op)∧.negative(n)
if (zero(n)) return id;
return power(a, n, op);
}
项目3.1浮点乘法和加法不可结合,用于作为power或powerleftassociated的运算就可能得到不同结果.请设法弄清,在求浮点数的整数次幂时,是power还是powerleftassociated能给出更准确的结果.