我们在年看到了Miller-Rabin和Baillie-Wagstaff的素性测试以前的 练习今天,我们来看一下Robert M.Solovay和Volker Strassen在1977年开发的一项测试。该测试已被其他两个测试取代,不再使用,但在RSA密码系统的开发中具有重要历史意义。

测试基于欧拉准则,其中指出(第页−1)/2≡ (/第页)(修订版第页)对于任何奇数质数第页和任意整数在范围2到第页−1(带gcd)(,第页)=1,其中(/第页)是Legendre符号。如果一个数字n个被测试是首要的,测试将表明n个是质数;如果是一个数字n个被测试的是复合,测试将表明它要么是质数,要么是具有相同概率的复合,就像掷硬币一样。因此,Solovay-Strassen测试选择k个不同的证人; 如果他们中有人表示n个是复合的,那么它必须是复合的n个是复合的,它被认为是赔率为2的素数k个.

如果你愿意假设扩展黎曼假设的真理,那么通过测试所有素数,Solovay-Strassen检验可以成为素性的绝对证明在2到min的范围内(n个−1,对数2 n个); 如果没有表示的复合性n个,然后n个是ERH上的prime。

Solovay-Strassen检验不再使用,原因有三:首先,它需要更多的工作才能实现,因为它涉及雅可比符号和模幂运算,而Miller-Rabin检验只涉及模幂运算。其次,Miller-Rabin检验有更好的误差范围,k个−4与相比k个−2第三,所有欧拉证人也都是米勒·拉宾强有力的证人,证明了n个ERH上存在绝对原始性证据也不妨碍使用Miller-Rabin检验,因为有一个基于Miller-Labin有力证人的类似原始性证据。

您的任务是编写两个版本的Solovay-Strassen素性测试,一个是概率测试,另一个是ERH测试。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

装配工,第3部分

2014年4月23日

我们研究了一个简单的汇编程序,用于两个以前的 练习。今天,我们通过编写一个程序来完成对汇编程序的了解,该程序可以生成整洁的列表,例如下面这个示例程序:

#打印输入数字的总和(以零结尾)000:03010 ld zero#将总和初始化为零001:04011总金额002:01000循环get#读取数字003:08007 jz完成#如果数字为零,则不再输入004:05011添加sum#将输入添加到累计总和005:04011 st sum#将新值存储回sum006:09002 j loop#返回并读取另一个数字007:03011完成ld sum#打印sum008:02000放009:10000停机010:00000零常数0011:00000和常量

该列表在第一列显示内存地址,在第二列显示程序开头的内存内容,在第三列显示助记符标签,在第四列显示操作码,在第五列显示操作对象,在第六列显示注释。

您的任务是编写一个生成汇编程序列表的程序。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

装配工,第2部分

2014年4月18日

上一次练习我们为一台假想的计算机构建了一个汇编程序。今天,我们为这台假想的计算机编写了一个模拟器。基本思想很简单:从位置0的程序计数器开始,要么在该位置执行操作并将程序计数器前进到下一个位置,要么将程序计数器设置为跳转指令的对象。

你的任务是编写模拟器。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

装配工,第1部分

2014年4月15日

在这个练习和下一个练习中,我们将为假设的计算机编写一个简单的汇编程序;我们在遵循书中的汇编程序Awk编程语言由Alfred V.Aho、Brian W.Kernighan和Peter J.Weinberger撰写。我们的计算机有一千个五位数单词的内存、一个累加器和十一个操作码:

OPCODE公司 说明 描述
00 常数C 定义常量的汇编伪运算符C类
01 得到 从累加器的输入端读取一个数字
02 将累加器中的数字写入输出
03 ld米 用内存位置的内容加载累加器M(M)
04 st M公司 将累加器的内容存储在内存位置M(M)
05 添加M 添加内存位置的内容M(M)至蓄能器
06 子M 减去内存位置的内容M(M)来自蓄能器
07 jpos M格式 跳转到内存位置M(M)如果蓄能器为正极
08 jz M公司 跳转到内存位置M(M)如果蓄能器为零
09 j个 跳转到内存位置M(M),无条件
10 停止 停止程序执行

汇编语言程序是一系列空行和语句,最多由四个字段组成:第一个字段(如果存在)是一个标签;它必须从行的第一个位置开始,不能以数字开始。第二个字段是操作码,是必填字段;它遵循可选标签和必填空格。第三个字段是对象,它只用于某些操作码;如果存在,它将跟随操作码和必填空格。第四个字段是可选的,是注释;哈希签名之后的行中的所有内容都将被忽略。下面是一个示例汇编语言程序,它打印用户输入的一系列整数的总和,输入的末尾用0标记:

#打印输入数字的总和(以零结尾)ld zero#将总和初始化为零第一笔款项循环获取#读取一个数字jz done#如果数字为零,则不再输入add sum#将输入添加到累计总和st sum#将新值存储回sumj循环#返回并读取另一个数字done ld sum#打印总和停止零常数0总和常数

加载示例程序后的内存内容显示在下一页。

你的任务是编写一个程序,将用我们简单的汇编语言编写的程序汇编并加载到内存中;在下一个练习中,我们将为我们假设的计算机编写一个模拟器。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

绘图仪

2014年4月11日

创建图形和图表的程序是许多商业和技术工作中的重要工具;例如,程序员可能会在程序调试运行期间查看内存使用情况图,以确定需要修剪的热点。

一种简单的图形是散点图,有时也称为x/y图。输入是x,y网格上的点列表;输出是一张在网格上绘制点的图片。一个简单的输入文件出现在下一页.

您的任务是编写一个程序来绘制散点图。完成后,欢迎您阅读运行一个建议的解决方案,或者发布你自己的程序,或者在下面的评论中讨论练习。

页:1 2

格式化输出

2014年4月8日

标准Scheme提供的唯一输出功能是显示,用于普通输出,以及,用于系统格式输出。这相当有限。在另一个极端,Lisp提供了格式函数,它有比您想象的更多的选项(在我放弃它以支持HyperSpec(超级规范),我的CLtL2打印本的书脊被折断了两处,格式). 许多语言提供某种格式的输出-有人记得吗照片在COBOL中?在今天的练习中,我们将实施打印由C语言推广并在多种语言中使用的函数。

打印家庭:(冲刺 柔性制造技术 快递)返回根据给定规范格式化的字符串格式并包含值快递…; (打印 柔性制造技术 快递)显示格式类似于的字符串把格式数据写成串至电流输出端口,以及(fprintf(打印) 港口 柔性制造技术 快递)显示格式类似于的字符串把格式数据写成串到指定的港口. The柔性制造技术港口参数总是必需的。

这个柔性制造技术参数是一个字符串,其中包含文本、转义序列和快递应格式化会话。规范由文字百分比符号组成%,零个或多个修饰符,以及一个单字符说明符。我们将支持的单字符说明符是:

c(c)ascii字符
d日十进制整数
(f)浮点数
o(o)八进制整数
一串
x个十六进制整数
%文字百分号

应该有这么多快递中有格式说明符柔性制造技术字符串,除了%文字百分号说明符不使用快递会话。文字百分号之间最多可以出现四个修饰符%开始说明符和结束说明符的单字符说明符:

-left—调整快递会话在其领域;如果没有给出快递分裂是正当的
0带前导零而不是空格的左图
宽度使用空格(或零)将字段填充到此宽度
.前c小数点右边的数字,或最大字符串长度

修饰符必须按上述顺序显示。这个宽度前c参数是无符号十进制整数。

转义序列由反斜杠引入;支持以下转义序列:

\b条退格
\(f)表单馈送
\n个换行符
\第页回车
\t吨水平选项卡
\ddd(ddd)具有八进制值的字符ddd(ddd),其中ddd(ddd)是介于0和7之间的1到3位数字
\c(c)任何其他字符c(c)例如,从字面上看\\反斜杠或\"用于引号

根据环境的不同,换行可能(也可能不)意味着回车符或vice-versa。下一页给出了几个示例。

您的任务是编写一个函数,使用的定义为您的语言提供格式化的输出打印或其他适合您的语言和愿望的规范。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

自行车链保理

2014年4月4日

作为对愚人节取笑你的忏悔,我还有一个关于因子分解的练习。今天我们将模拟一台由Derrick H Lehmer(著名的岳父-岳父三人组数学家Lehmer的儿子)发明的机器,该机器使用自行车链对整数进行因子分解。与前面的练习不同,这个因子分解方法是真实的;事实上,该方法的一个变体是20世纪30年代中期到60年代中期对整数进行因子分解的最佳可用方法,莱默的机器为坎宁安项目找到了许多有价值的因子分解。我们今天将讨论机器的简化版本,如下所述乌利·梅耶以及未来练习中的完整版本的机器。我找不到莱默机器的无版权图片,但如果您有兴趣,可以访问电脑类 历史 博物馆或者去见莱默本人描述机器.

该机器基于费马的平方差因式分解方法:如果n个=x个22然后是因素n个是(x个)和(x个+). 费马的方法始于= ⌈ √n个⌉,计算2n个,当结果为平方时停止。

莱默的机器通过观察二次剩余来识别可能的平方。一个整数是二次剩余模n个如果有一些x个这样的话x个2(修订版n个). 对于一个数字2n个要在费马算法中成为一个正方形,它必须是许多小基的二次剩余。Lehmer的机器将二次剩余表示为自行车链上的“开放”点,然后沿公共轴旋转许多不同长度的自行车链,当所有的链都是二次剩余时停止;在许多但并非所有情况下,这样的数字将表示一个系数n个.

乌利·迈耶给予一个更好的描述,显示了一个有用的图表,并提供了他的乐高筛机的照片。

你的任务是编写一个程序,模拟莱默机器对整数进行因子分解。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

几天前,在/r/加密在时间O(log^4)内运行的新因子分解算法n个). A类纸张描述了算法。更好的是,新算法的编码很简单:

1) 设置n个.
2) 快递作为其十进制数字的列表。
3) 将每个十进制数字表示为二进制位列表。
4) 附加二进制位的单独列表。
5) 将生成的二进制位列表转换为十进制数。叫它吧d日.
6) 如果的最大公约数n个d日介于1和之间n个,这是一个因素n个.报告因素并停止。
7) 设置d日并转至步骤1。

步骤1到4形成数字代码一个数字。例如,88837构成了位列表1 0 0 0,1 0 0,10 0 0,11,11 11,其中我们使用逗号来表示十进制数字。该位列表是十进制的69919,即88837的数字代码。要找到88837的因子,请计算连续的数字代码,直到gcd大于1;链的长度为88837、69919、54073、2847、2599、5529、2921、333,此时gcd(88837,333)=37,我们发现了一个因子:88837=74× 37. 对96577进行因子分解更快:96577的数字代码是40319,gcd(96577,40319)=23,即96577=13×17×19×23的因子。但尝试因子65059=17×43×89会导致无限循环。本文给出了该问题的启发式解决方案,但我们将到此为止,接受有时因子分解失败的事实。

您的任务是编写一个通过数字编码进行因子分解的函数。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2