证明tmult_ok的正确性
csapp page124. practice problem 2.35
/* Determine whether arguments can be multiplied without overflow */
int tmult_ok(int x, int y){
int p = x*y;
/* Either x is zero, or dividing p by x gives y */
return !x || p/x == y;
}
函数 tmult_ok 的功能是检查两个二补数相乘会不会溢出, 逻辑是,要么 x 为零, 或者 乘积 p 除以 x 等于另一个乘数 y 的话,就说明不会溢出。
这题要求给出这个函数正确性的数学证明。首先证明当x=0这个情况的正确性。然后考虑w位的数字(w不等于0) 有 y, p, 和 q, 其中 p 是x, y执行了二补码乘法后的结果, q 是 p/x 的值。
书中给出三条线索,分别给出这三条线索的证明即可证明这个函数的正确性。
- 证明: x和y的整数相乘结果可以被写成 \(x*y = p + t*2^w\) 形式, 当且仅当 t != 0 的时候,p溢出。
- 证明: p 可以被写成 \(p = x * q + r\), 其中\(|r| < |x|\).
- 证明: 当且仅当 \(r = t = 0\) 的时候 \(q = y\).
答案是这么证明的:
1.因为x,y都是w位二补码表示的数,所以他们的乘积最多要用2w位表示,因为:
\(-2^{w-1} <= x, y <=2^{w-1} - 1\) 注:这是二补码的取值范围
所以 x*y 就要 大于等于 \(-2^{w-1} * (2^{w-1} - 1)\) 就等于 \(-2^{2*w - 1} + 2^{w - 1}\) 注: 其实就是Tmax*Tmin
小于等于 \((-2^{w - 1})^2\) 就等于 \(2^{2*w - 2}\) 注: 其实就是Tmin*Tmin,可以证明Tmax^2 没有 Tmin^2大
看见2的次方数是2w起跳的,就说明肯定得要2w位才能表示了。所以 x*y 理应是要用 2w 位表示的(但是2w位是溢出的,暂时不管),现在设 u 等于该乘积低w位的无符号形式,v 等于该乘积高w位的二补码形式。
那么,根据公式2.3 即二进制到二补码的转换公式可以得出 \(x*y = v*2^w + u\) 这个式子乍一看匪夷所思,怎么能把一个位向量劈成两半,前w位按二补码算然后乘以\(2^w\) ,后w位按无符号算然后两个部分加起来怎么刚好就是x和y的乘积??
其实只要根据二进制转二补码的公式细心推倒,马上就可以证明这个结论:
我们还知道 \(u = T2U_{2w}(p)\) 这里p是二补码乘积,因为实际上不管乘积结果有没有溢出,unsigned形式和tow's complement形式的乘积在w位上是一模一样的,这点在数的2.18给出了证明。
所以根据公式T2U 得 \(u = p_{w-1} * 2^w + p\), 把u 带入之前的 \(x*y = v*2^w + u\) 这里, 化简可以得到: \(x*y = 2^w * (v + p_{w-1}) + p\), 此时我们设 \(t = v + p_{w-1}\),公式变为:\(x*y = t* 2^w + p\)
这里我们就可以看出,当且仅当 t = 0 的时候, x*y 才等于p,t 不等于 0 的时候乘积是溢出的。到这里证明了上面的第1条。
2.因为无论 x*y 的值 p 有没有溢出,总之它是个整数,那么只要 p 是个整数,它除以一个非零整数 x 必然会得到一个商(q)和一个余数(r) 使得 \(p = x * q + r\) 其中 |r| < |x|
这里取绝对值是因为r 和 x 的符号可能不一样,比如 -7 / 2 得 -3 余 -1, |-1| < |2|。 这里证明了第2条。
3. 如果 q = y 根据 \(p = x*q+r\) 得出 \(p = x*y+r\) 其中 \(x*y = t * 2^w + p\) 所以 \(p = t*2^w + p + r\), 两边消去 p 以后得到 \(t*2^w = -r\) 要让这个等式成立,有两种情况,要么等号两边值相等,要么两边都为零。
在第2条的证明中,我们得出 |r| < |x|, 而x是二补码,所以绝对值的最大值是 2^w 所以 |r| < \(2^w\), 回到这里,等式左边出现了\(2^w\) 而 r 要比\(2^w\) 小,可见其值必不相等,则必须是为零的情况。所以必须 r = t = 0
根据第1条证明,我们知道要想乘积不溢出,t 必须为 0, 根据第三条,当且仅当 t 为 0 的时候 \(p / x = y\) 用程序表示就是 (!x || p / x == q) 这个逻辑被证明是正确的。
这样3也证明了,再看x=0的情况,x等于零的时候乘积为零肯定不会溢出嘛,所以这个程序是正确可靠的。证毕。
证明tmult_ok的正确性的更多相关文章
- 循环不变量loop invariant 与 算法的正确性
在论述插入排序的正确性的时候, 书中引入了循环不变量的概念, 刚开始稍微有点不太明白, 早上查了一波资料之后决定把自己的理解记录下来. 什么是循环不变量 ? 在我看来, 所谓循环不变量的就是一个在循环 ...
- 证明:寝室分配问题是NPC问题
P.NP.NPC.NP-hard P:多项式时间能够解决的问题的集合,比如最短路径问题是集合P的一个元素,而最短路径问题本身又是一个集合,因此P是集合的集合. NP:多项式时间内能够验证的问题的集合. ...
- RapidJSON 代码剖析(四):优化 Grisu
我曾经在知乎的一个答案里谈及到 V8 引擎里实现了 Grisu 算法,我先引用该文的内容简单介绍 Grisu.然后,再谈及 RapidJSON 对它做了的几个底层优化. (配图中的<Grisù& ...
- 两个int的和判断溢出
long a,b; cin>>a>>b; long i; i = a+b; if((i^a)<0 && (i^b)<0) cout<<& ...
- BZOJ1828 [Usaco2010 Mar]balloc 农场分配
直接贪心,我们把线段按照右端点从小到大排序,然后一个个尝试插入即可... 来证明贪心的正确性: 不妨设贪心得到的答案集合为$S$,最优解的答案集合为$T$ 若$S$不是最优解,那么$S \not= T ...
- algorithm -- 插入排序
插入排序是<算法导论>中第一个介绍的算法,详细分析了插入排序的原理,执行过程,证明了算法的正确性.同时也引出了算法分析和算法分析常用的方法. 此文对原文作个转述,检验学到的知识. 文中使用 ...
- Codeforces Round #173 (Div. 2)
A. Bit++ 模拟. B. Painting Eggs 贪心,每个物品给使差值较小的那个人,根据题目的约数条件,可证明贪心的正确性. C. XOR and OR \(,,00 \to 00,01 ...
- M1M2总结
这个学期很开心可以和一帮兄弟姐妹们一起做软件写代码,总体看下来真的是充满哦了艰辛和困苦.虽然我是负责软件测试的这一块的,但是看着他们辛苦的写代码我也很是为他们着急和心疼.毕竟,编译当头,数据库辅助,每 ...
- UOJ264 【NOIP2016】蚯蚓
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...
随机推荐
- Codeforces 519 E. A and B and Lecture Rooms
Description 询问一个树上与两点距离相等的点的个数. Sol 倍增求LCA. 一棵树上距离两点相等,要么就只有两点的中点,要么就是与中点相连的所有点. 有些结论很容易证明,如果距离是偶数,那 ...
- BZOJ 4665: 小w的喜糖
Sol DP+容斥. 这就是一个错排的扩展...可是想到容斥却仅限于种数的容斥,如果种数在一定范围内我就会做了QAQ. 但是容斥的是一定在原来位置的个数. 发现他与原来的位置无关,可以先把每个同种的糖 ...
- php判断浏览器语言
<?php // 分析 HTTP_ACCEPT_LANGUAGE 的属性 // 这里只取第一语言设置 (其他可根据需要增强功能,这里只做简单的方法演示) preg_match('/^([a-z\ ...
- bootstrap框架-----可见 隐藏
可见框架-像素选择 -block-inline :块内联元素 -inline-block将对象呈递为内联对象,但是对象的内容作为块对象呈递.旁边的内联对象会被呈递在同一行内,允许空格 可以设置宽度和 ...
- phpcms评论的url替换问题
在整个项目改ip之前,评论里的url是127.0.1.113 改成localhost之后,更新了所有的url和缓存,但是v9_comment表中的url字段没有更新. 想一下后台只有一个地方是替换数据 ...
- 页面遮罩层,并且阻止页面body滚动。bootstrap模态框原理
实现思路: 1.需要有一个层将body遮住,放在body上方. 2.修改body的overflow属性值为:hidden 废话不多说了,将关键代码贴出来了,兼容火狐,谷歌,ie 遮罩层的样式代码,红色 ...
- ACM/ICPC 之 数据结构-线段树思想(POJ2182,含O(n^2)插入式解法)
这道题在一定程度上体现了线段树的一种用法,解决的问题是:对于总计n个元素的第i个元素,已知其在[1,i]上部分序列的排名,求第i个元素在所有n个元素中的排名. 当然这道题数据比较水,所以用O(n^2) ...
- nyoj756_重建二叉树_先序遍历
重建二叉树 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 题目很简单,给你一棵二叉树的后序和中序序列,求出它的前序序列(So easy!). 输入 输入有多组数 ...
- GridView中使用分页控件
前台:导入<%@ Register assembly="AspNetPager" namespace="Wuqi.Webdiyer" tagprefix= ...
- August 11th 2016, Week 33rd Thursday
A particular fine spring came around. 转眼又是一番分外明媚的春光. Hey, it is hot outside, sometimes even unbearab ...