2020-BUAA OO-面向对象设计与构造-HW11中对ageVar采用缓存优化的等价性证明(包括溢出情况)
HW11中对ageVar采用缓存优化的等价性证明(包括溢出情况)
概要
我们知道,第三次作业里age上限变为2000,而如果缓存年龄的平方和,2000*2000*800 > 2147483647,会溢出。但是实际上,我们仍然能通过缓存得到正确的结果。这是因为,计算机内进行的二进制运算其实每一步都进行了 \(\&0xffff\_ffff\) 操作,有交换律、结合律、平方公式成立。即使在溢出的情况下,两个式子仍然是等价的。本文试着利用二进制运算和无符号数运算的关系,以及无符号数运算的性质,来证明这一点。
引论
无符号数的运算和二进制的运算
我们知道,在机器语言里,不管一个字是有符号数还是无符号数,采用的四则运算指令都是相同的(MIPS中add和addu的区别也只是是否会触发算术溢出异常,而具体的运算方式仍是一样的)。
我们现在Java程序里,做的其实是上述计算机里的二进制运算,和数学世界的运算是有所不同的。我们将计算机二进制的“四则运算”分别记为 \(\dot{+} \quad \dot{-} \quad \dot{*} \quad \dot{/}\) 。
这四种运算肯定不是随便定义的,和现实中的数学运算肯定有着一定的关系。这里我们尝试从无符号数的角度,建立计算机二进制运算和无符号数运算之间的关系。(我们在这里不讨论除法,因为这和我们的主题无关 因为除法很麻烦作者根本不会(x))
为此,我们引入一些记号。同一个32位二进制数据,既可以表示一个无符号整数,又可以表示为一个有符号整数。我们将某个数据记为 \(d\) ,记 \(U(d)\) 为按无符号数解释 \(d\) 得到的数字,\(T(d)\) 为按二的补码有符号数解释 \(d\) 得到的数字。我们将相应的逆过程,将一个数字按照有/无符号数解读并转化为二进制数据的过程,记作 \(UD(x)\) / \(TD(x)\)。
根据我们已有的知识,在未发生溢出的情况下,计算机二进制运算的结果 和 把二进制数据解读为无符号数进行运算的结果 是相同的。现在我们主要需要考虑的内容是:数学中的无符号数是无位数限制的。结合这一点,我们可以得到:
\(U(a \dot{+} b) = (U(a) + U(b)) \% 0x1\_0000\_0000\)
\(U(a \dot{-} b) = (U(a) - U(b)) \% 0x1\_0000\_0000\)
\(U(a \dot{*} b) = (U(a) * U(b)) \% 0x1\_0000\_0000\)
其中a,b为两个二进制数据。
进一步
\(a \dot{+} b = UD((U(a) + U(b)) \% 0x1\_0000\_0000)\)
\(a \dot{-} b = UD((U(a) - U(b)) \% 0x1\_0000\_0000)\)
\(a \dot{*} b = UD((U(a) * U(b)) \% 0x1\_0000\_0000)\)
其中a,b为两个二进制数据。
取模运算
此处参考了取模运算的性质 By varinic
(取模和取余似乎还略有不同,我不太懂这个,所以用了本文几乎全程使用无符号数来避开这个问题。
基本性质
若p|(a-b),则a≡b (% p)。例如 11 ≡ 4 (% 7), 18 ≡ 4(% 7)
(a % p)=(b % p)意味a≡b (% p)
对称性:a≡b (% p)等价于b≡a (% p)
传递性:若a≡b (% p)且b≡c (% p) ,则a≡c (% p)
运算规则
模运算与基本四则运算有些相似,但是除法例外。其规则如下:
(a + b) % p = (a % p + b % p) % p (1)
(a - b) % p = (a % p - b % p) % p (2)
(a * b) % p = (a % p * b % p) % p (3)
a ^ b % p = ((a % p)^b) % p (4)
结合律:
((a+b) % p + c) % p = (a + (b+c) % p) % p (5)
((a*b) % p * c)% p = (a * (b*c) % p) % p (6)
交换律:
(a + b) % p = (b+a) % p (7)
(a * b) % p = (b * a) % p (8)
分配律:
((a +b)% p * c) % p = ((a * c) % p + (b * c) % p) % p (9)
证明
我们想要证明的是:我们利用缓存的算式和JML对ageVar的算式是等价的。
注意,JML中的加法也是计算机里的二进制加法。
我们以下提到的变量都指他们的二进制数据。
缓存:
\]
JML:
\]
我们只需要证明分式的上半部分恒等。
为了方便,我们记\(M(U(d)) = U(d) \% 0x1\_0000\_0000\)
证明平方式对二进制运算成立
首先,针对每一个小单元
\]
\]
(这什么鬼玩意)
我们注意到 \(U(UD(x)) = x\),x为一个无符号数,配合利用(1)(2)(3)三条运算规律可以去掉多余的\(M()\)记号,化简一下:
\]
\]
再次利用(1)(2)(3)三条运算规律,在适当位置增加冗余的\(M()\)记号来运用我们的无符号数-二进制数互换。我们就有了:
\]
P.S.:写到后面我发现直接证二进制运算有分配律,加上后面的交换律结合律不就直接成了(瘫
证明交换律对二进制运算成立
\]
证明结合律对二进制运算成立
\]
\]
\]
\]
\]
\]
\]
即证得
之后就是简单的变形了,就不再赘述。
总结
有了交换律,结合律和平方公式,我们很容易就能将JML给出的计算公式转化为我们用的利用了缓存的公式。而且这个转化过程经过数学证明是恒等的。不用管是否溢出,同样的二进制age数据,在二进制运算的条件下,用JML和缓存方法得到的ageVar数据一定是相等的。就算ageVar本身溢出了,我们得到的溢出后结果也会是一样的。
本文通篇使用无符号整数,是因为无符号整数运算和二进制数据运算的转换比较好处理,学过数论的大佬们也许可以用有符号整数的运算导出来类似的结果吧(咱是不会了。
至于担心age是负数的时候能不能用的,肯定是能用的,因为无符号数在这里就是一个介质。我们知道无符号数的运算性质,知道无符号数和二进制数据之间的关系,然后通过这些来求二进制数据的运算规律。换一个别的,应该也是能做的(不过可能更麻烦点)。
顺便,有的人说用了long可能会炸,其实是因为先做了除法再转成int。直观的例子就是一个刚好溢出int一点点,但是/n之后在int范围内的结果的数,long先做除法再转int就会是正的,long先转int再除就是负的了。数学上来说,因为除法的模p运算性质不像加减乘那么好,而long相当于%0x1_0000_0000_0000_0000和int不同,就炸了。
咱数学学的不好,也没搞过数论啊这些,所以如果有错还请不要过分嘲笑(正色(x)),发现问题的话就麻烦在讨论区提点一手,我会及时更正。
2020-BUAA OO-面向对象设计与构造-HW11中对ageVar采用缓存优化的等价性证明(包括溢出情况)的更多相关文章
- 从结构和数字看OO——面向对象设计与构造第一章总结
不知不觉中,我已经接触OO五周了,顺利地完成了第一章节的学习,回顾三次编程作业,惊喜于自身在设计思路和编程习惯已有了一定的改变,下面我将从度量分析.自身Bug.互测和设计模式四个方向对自己第一章的学习 ...
- BUAA面向对象设计与构造——第二单元总结
BUAA面向对象设计与构造——第二单元总结 第一阶段:单部傻瓜电梯的调度 第二阶段:单部可捎带电梯的调度 (由于我第一次写的作业就是可捎带模式,第二次只是增加了负数楼层,修改了一部分参数,因此一起总结 ...
- BUAA面向对象设计与构造——第一单元总结
BUAA面向对象设计与构造——第一单元总结 第一阶段:只支持一元多项式的表达式求导 1. 程序结构 由于是第一次接触面向对象的编程,加之题目要求不算复杂,我在第一次作业中并没有很好利用面向对象的特点, ...
- 面向对象设计与构造:oo课程总结
面向对象设计与构造:OO课程总结 第一部分:UML单元架构设计 第一次作业 UML图 MyUmlInteraction类实现接口方法,ClassUnit和InterfaceUnit管理UML图中的类和 ...
- 【设计模式系列】之OO面向对象设计七大原则
1 概述 本章叙述面向向对象设计的七大原则,七大原则分为:单一职责原则.开闭原则.里氏替换原则.依赖倒置原则.接口隔离原则.合成/聚合复用原则.迪米特法则. 2 七大OO面向对象设计 2.1 单一 ...
- 面向对象设计与构造:JML规格单元作业总结
面向对象设计与构造:JML规格单元作业总结 第一部分:JML语言理论基础 JML语言是什么:对Java程序进行规格化设计的一种表示语言 使用JML语言有什么好处: 用逻辑严格的规格取代自然语言,照顾马 ...
- 2020-BUAA OO-面向对象设计与构造-第三单元总结
Part-1 JML总结 Section-1 理论基础 The Java Modeling Language (JML) is a behavioral interface specification ...
- 「BUAA OO Pre」 Pre 2总结回顾概览
「BUAA OO Pre」 Pre 2总结回顾概览 目录 「BUAA OO Pre」 Pre 2总结回顾概览 Part 0 前言 写作背景 定位 您可以在这里期望获得 您在这里无法期望获得 对读者前置 ...
- (转) 面向对象设计原则(二):开放-封闭原则(OCP)
原文:https://blog.csdn.net/tjiyu/article/details/57079927 面向对象设计原则(二):开放-封闭原则(OCP) 开放-封闭原则(Open-closed ...
随机推荐
- NGK算力市场,不止有动静态收益还有SPC空投!
随着数字货币交易的火热,云算力挖矿也悄然崛起.越来越多的用户开启云算力挖矿,以获取更多的收益.相较于传统的矿机挖矿,用户通过购买算力进行云挖矿,节省了购买矿机以及维护的成本.另一方面,也降低了安全风险 ...
- 经典面试题:在浏览器地址栏输入一个 URL 后回车,背后发生了什么
尽人事,听天命.博主东南大学硕士在读,热爱健身和篮球,乐于分享技术相关的所见所得,关注公众号 @ 飞天小牛肉,第一时间获取文章更新,成长的路上我们一起进步 本文已收录于 CS-Wiki(Gitee 官 ...
- 玩遍博客网站,我整理了 Hugo 及其流行的风格主题
搭建博客网站是个人进入互联网世界的最常见方式之一.伴随着网站技术的发展,如何搭建博客网站已经变得非常容易了.当然,你可以选择诸如 新浪博客.CSDN.博客园 之类的大型网站,快速创建依赖于大平台的个人 ...
- JS中try catch的用法
在js中也可以使用try/catch语法,把可能发生异常的代码使用try包裹起来,然后在catch中对异常进行处理,处理后就不会影响后面代码的执行. const a = null try { cons ...
- Prometheus+Grafana+Alertmanager搭建全方位的监控告警系统
prometheus安装和配置 prometheus组件介绍 1.Prometheus Server: 用于收集和存储时间序列数据. 2.Client Library: 客户端库,检测应用程序代码,当 ...
- molloc堆区的动态内存分配
[前言]前面有一篇文章介绍了堆区栈区的区别.栈区的核心主要集中在操作一个栈结构,一般由操作系统维护.堆区,主要是我们程序员来维护,核心就是动态内存分配. 这篇笔记结束就不在高新CSAPP的读书笔记了, ...
- Deep Unfolding Network for Image Super-Resolution 论文解读
Introduction 超分是一个在 low level CV 领域中经典的病态问题,比如增强图像视觉质量.改善其他 high level 视觉任务的表现.Zhang Kai 老师这篇文章在我看到的 ...
- 图文详解:阿里宠儿【小兔】RabbitMQ的养成攻略
- 184. 部门工资最高的员工 + join + in
184. 部门工资最高的员工 LeetCode_MySql_184 题目描述 题解分析 1.首先需要使用group by找出工资最高的值 2. 然后考虑到最高工资的可能有多位,所以使用in语句找到所有 ...
- PAT-1140(Look-and-say Sequence)字符串处理
Look-and-say Sequence PAT-1140 #include<iostream> #include<cstring> #include<string&g ...