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 ...
随机推荐
- 安装 Angular Material UI
文档 调色板 安装 ng add @angular/material ? Choose a prebuilt theme name, or "custom" for a custo ...
- 「NGK每日快讯」2021.2.3日NGK公链第92期官方快讯!
- redis5.* 手动构建集群
1.集群的概念 集群是一组相互独立的.通过高速网络互联的计算机,它们构成了一个组,并以单一系统的模式加以管理.一个客户与集群相互作用时,集群像是一个独立的服务器.集群配置是用于提高可用性和可缩放性.当 ...
- Dev GridControl列绑定LookUpEdit数据源:默认值
在Winform开发过程中,GridControl控件是比较常见的,尤其是其数据源的灵活性,为我们提供了不少的便利. 在使用Dev的GridControl的时候,有时候会在列的Column Edit属 ...
- Filter理解
web中Filter通过<init-param>添加参数.web.xml中的配置: <filter> <filter-name>AuthFilter</fil ...
- Django Admin 配置和定制基本功能(基本二次开发配置)
一 列表显示页面 1. list_display,列表时,定制显示的列 @admin.register(models.UserInfo) class UserAdmin(admin.ModelAdm ...
- 使用Mongodb设计评论系统
1:如何设计数据存储结构 1.1:mysql 1:评论表 2:回复表(评论的评论) 1.2:mongodb 不需要两张表,一个collection 就可以搞定. 数据结构如图: 通过对象数组中的字段作 ...
- RabbitMQ之死信队列
1:何为死信队列 死信队列也是一个正常的队列,可以被消费. 但是,死信队列的消息来源于其他队列的转发. 2:如何触发死信队列 1:消息超时 2:队列长度达到极限 3:消息被拒绝消费,并不再重进队列,且 ...
- WPF -- DataTemplate与ControlTemplate结合使用
如深入浅出WPF中的描述,DataTemplate为数据的外衣,ControlTemplate为控件的外衣.ControlTemplate控制控件的样式,DataTemplate控制数据显示的样式,D ...
- CRLF注入原理
CRLF 指的是回车符(CR,ASCII 13,\r,%0d) 和换行符(LF,ASCII 10,\n,%0a),操作系统就是根据这个标识来进行换行的,你在键盘输入回车键就是输出这个字符,只不过win ...