《编程原本 》一2.1 变换

2.1 变换

虽然从任意一组类型到任意类型的函数都存在,但是有些具有特殊签名的函数类更为常用.本书中经常用的是两类函数:同源谓词和同源运算.同源谓词在形式上都是Tו••× T → bool;同源运算都是形如Tו••× T → T的函数.一般而言存在着任意的n元谓词和n元运算,但实际中遇到最多的还是一元和二元的同源谓词,一元和二元的同源运算.
谓词是返回真值的函数:

Predicate(P).FunctionalProcedure(P)∧Codomain(P)=bool

同源谓词也是同源函数:

HomogeneousPredicate(P).
Predicate(P)∧HomogeneousFunction(P)

一元谓词只有一个参数:

UnaryPredicate(P).Predicate(P)∧UnaryFunction(P)

运算是同源函数,其值域与作用域相同:

Operation(Op).HomogeneousFunction(Op)∧Codomain(Op)=Domain(Op)

下面是几个同源运算的实例:

int abs(int x) { 
if (x < 0) return -x; else return x; 
} //一元运算
double euclidean norm(double x, double y) { 
return sqrt(x * x + y * y); 
} //二元运算
double euclidean norm(double x, double y, double z) { 
return sqrt(x * x + y * y + z * z); 
} //三元运算

引理2.1euclidean_norm(x,y,z)=euclidean_norm(euclidean_norm(x,y),z)
这一引理说明上面的三元运算可以从相应的二元版本得到.但是,由于效率,表达方便,或者准确性等原因,这样的三元运算也可以纳入处理三维空间的程序的计算基.

如果一个过程的定义空间是其输入类型的直积的子集,就称该过程为部分的(partial);如果其定义空间等于其输入类型的直积,则说它是全的.按标准的

数学习惯,我们也认为部分过程包括全过程,并称那些不是全的部分过程为非全的(nontotal).由于计算机表示的有穷性,有些全函数在计算机里的实现却是非全的.例如,有符号的32位整数加法就是非全的.

一个非全过程需要有一个描述其定义空间的前条件.要验证对这个过程的一个调用是正确的,必须确定所给的实参满足这一前条件.有时我们会把部分过程作为参数传给一个算法,因此需要在运行时确定这种过程参数的定义空间问题.为了处理这类情况,我们将定义一个定义空间谓词(de.nitionspacepredicate),它与这一过程参数的输入相同,当且仅当实际输入在这个过程的定义空间里时,让这个谓词返回真.在调用一个非全过程之前,或者其前条件必须满足,或者该调用是用这个过程的定义空间谓词保护的.

练习2.1请为32位有符号整数的加法实现一个定义空间谓词.
本章研究一元运算,我们称其为变换(transformation):

Transformation(F).
Operation(F)
∧UnaryFunction(F)
∧DistanceType:TransformationInteger
→

这里的DistanceType将在下一节讨论.
变换可以自组合(selfcomposable),例如可以写f(x),f(f(x)),f(f(f(x))),等等.f(f(x))的定义空间是f的定义空间和结果空间的交.这种自组合能力和检查相等能力的结合,使我们可以定义许多有趣的算法.
设f是一个变换,它的幂(power)定义如下:

.
.x if n = 0, fn(x)=. 
.fn.1(f(x))ifn>0
.

要实现计算fn(x)的算法,就要描述对一个整数类型的需求.第5章将研究描述与整数有关的一些概念,现在我们暂时依靠对整数的一些直观理解.有符号和无符号的整数类型都是整数的模型,还有任意精度的整数等,它们都包含下面的运算和文字量:
18 第2 章变换及其轨道
image

其中的I是一个整数类型.
这样就可以写出下面算法:

template requires(Transformation(F) && Integer(N)) Domain(F) power unary(Domain(F) x, N n, F f)
{
// 前条件: n . 0 ∧ (.i ∈ N) 0 while (n != N(0)) {n = n -N(1);x = f(x);
}
return x;
}

编程原本》提供了有关编程的一种与众不同的理解。其主旨是,实际的编程也应像其他科学和工程领域一样基于坚实的数学基础。本书展示了在实际编程语言(如C++)中实现的算法如何在最一般的数学背景中操作。例如,如何定义快速求幂算法,使之能使用任何可交换运算。使用抽象算法将能得到更高效、可靠、安全和经济的软件。 这不是一本很容易读的书,它也不是能提升你的编程技能的秘诀和技巧汇编。本书的价值是更根本性的,其终极目标是提升你对编程的洞察力。要想从中大获裨益,你需要从头到尾认真学习:阅读代码,证明引理,完成练习。到结束之时,你将看到如何把这里讨论的演绎方法应用到你的程序中,保证你做出的软件部件能一起工作,并表现出它们所应该表现的行为。 书中给出的算法和需求针对某些被操作的类型。有关这些描述的代码(也可以通过Web得到)采用C++的一个小子集书写,这样做是为了让所有有经验的程序员都能理解。这个小子集可以看做一种特殊语言,是由Sean Parent和Bjarne Stroustrup一起设计的。 无论你是一位软件开发者,还是其他以编程作为一项重要活动的专业人员,或者是一名在校的学生,你都会逐渐理解本书的经验丰富的作者多年来一直在教授和阐释的道理:数学对于编程是绝好的东西,理论对于实际是绝好的东西。
本书将演绎方法应用于程序设计,讨论程序与保证它们能正确工作的抽象数学理论之间的联系。书中把理论的规程、基于这些理论写出的算法,以及描述算法性质的引理和定理一起呈现给读者。 第1章 基础 1 1.1 理念范畴:实体,类别,类属 1 1.2 值 2 1.3 对象 4 1.4 过程 6 1.5 规范类型 7 1.6 规范过程 8 1.7 概念 10 1.8 总结 14 第2章 变换及其轨道 15 2.1 变换 15 2.2 轨道 18 2.3 碰撞点 21 2.4 轨道规模的度量 27 2.5 动作 28 2.6 总结 29 第3章 可结合运算 31 3.1 可结合性 31 3.2 计算乘幂 32 3.3 程序变换 35 3.4 处理特殊情况的过程 40 3.5 参数化算法 43 3.6 线性递归 44 3.7 累积过程 47 3.8 总结 48 第4章 线性序 49 4.1 关系的分类 49 4.2 全序和弱序 51 4.3 按序选取 52 4.4 自然全序 62 4.5 派生过程组 63 4.6 按序选取过程的扩展 63 4.7 总结 64 第5章 有序代数结构 65 5.1 基本代数结构 65 5.2 有序代数结构 70 5.3 求余 72 5.4 最大公因子 76 5.5 广义gcd 79 5.6 Steingcd 81 5.7 商 82 5.8 负量的商和余数 84 5.9 概念及其模型 87 5.10 计算机整数类型 88 5.11 结论 89 第6章 迭代器 91 6.1 可读性 91 6.2 迭代器 92 6.3 范围 94 6.4 可读范围 97 6.5 递增的范围 106 6.6 前向迭代器 108 6.7 索引迭代器 113 6.8 双向迭代器 114 6.9 随机访问迭代器 115 6.10 总结 117 第7章 坐标结构 119 7.1 二叉坐标 119 7.2 双向二叉坐标 123 7.3 坐标结构 129 7.4 同构,等价和有序 129 7.5 总结 137 第8章 后继可变的坐标 139 8.1 链接迭代器 139 8.2 链接重整 140 8.3 链接重整的应用 147 8.4 链接的二叉坐标 151 8.5 结论 155 第9章 拷贝 157 9.1 可写性 157 9.2 基于位置的拷贝 159 9.3 基于谓词的拷贝 166 9.4 范围的交换 174 9.5 总结 178 第10章 重整 179 10.1 置换 179 10.2 重整 182 10.3 反转算法 184 10.4 轮换算法 188 10.5 算法选择 196 10.6 总结 200 第11章 划分和归并 201 11.1 划分 201 11.2 平衡的归约 207 11.3 归并 212 11.4 总结 218 第12章 复合对象 219 12.1 简单复合对象 219 12.2 动态序列 227 12.3 基础类型 233 12.4 总结 236 跋 237 附录 A 数学表示 241 附录B 程序设计语言 243 参考文献 253 索引 257
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值