且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

《编程原本 》一3.4 处理特殊情况的过程

更新时间:2022-09-26 10:49:30

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.4 处理特殊情况的过程

《编程原本 》一3.4 处理特殊情况的过程

练习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能给出更准确的结果.