[CINTA] 具体数论与代数阅读笔记——第一章 整数和二进制(含加、乘、除)

news/2024/11/18 9:34:05/文章来源:https://www.cnblogs.com/luyaoqi/p/18286979

前言

这本书说自己是计算机专业数学入门之入门,成为读者攻读其他经典著作的垫脚石,但个人以为足矣替换掉本校内不知所云的、抽象的、让学生考完后马上全忘的那些课程。本书的 GitHub 仓库在这里。

该笔记并非单纯的整理归纳,而是记录陆爻齐在书中找到的对自己很有感触的部分。

闲话少说,下面是笔记正文。

第一章 整数与二进制

1.1 二进制

基本性质

首先,有两条基本的性质

  1. 偶数二进制最末尾的比特是 0;奇数二进制最末尾的比特是 1;
  2. 在一个二进制数末尾增加一个 0 等同于在十进制中对这个数乘 2。
    反过来说,对一个十进制数进行乘 2 操作等同于对其二进制表达左移一个比特。

显然,比如 2 的二进制表示为 0010,3 为 0011, 4即 2*2 为0100。

思考

随后提出思考:请问,你认为对一个十进制数进行除 2 等于对其二进制表达右移一个比特吗?

陆爻齐的回答是:是的,对 3,出 2 得 1.5,0011 右移一个比特得 0001.1,正好为 1.5。对 2, 除 2 得 1,0010 右移一个比特得 0001,正好为1。

性质

接着在基于“考虑任意自然数 n,所谓 2 的 n 次方 (2^n) 只是不断对 1 乘 n 次 2”给出了两条性质
3、给定任意自然数 n, 十进制数 2^n 的二进制数表达就是在 1 后加 n 个 0;
4、给定任意自然数 n, 十进制数 2^n − 1 的二进制数表达就是 n 个 1;

结合一点例子就能认同,4 是 2 的 2 次方,即 1 后加 2 个 0,即 0100。1 是 2 的 0 次方,为 1 后加 0 个 0,即 0001。4 减 1 得 3,0011,就是 2 的 1 次方和 0 次方相加所得, 0011 = 0010 + 0001;2^2 - 1 = 2^1 + 2^0。

思考

接下来是作者给的思考,请将以上计算过程的结论归纳成一个定理,并证明。你可以使用任何的证明方法。
请问,以上“硬”算的方法能否推广为一种证明方法?

陆爻齐认为,可以归纳为,对任意自然数 n+1(n>=0),有\(2^{(n+1)} = \sum_0^n 2^n\)

位置计数法

如此,便引入了位置计数法,即对任意整数 b,有 \(b=\sum_{i=0}^{n-1}b_i2^i\),其中\(b_i\in\{0,1\}\)

显然,取 10,即 1010,可以视为 \(1010 = 1*2^3 + 0*2^2 + 1*2^1 + 0*2^0\),换句话 10 = 18 + 04 + 12 + 01。

加法与乘法

加法

加法,大家都能想到 a+b,但要是不准用 + 呢?

于是有下面这个加法的算法,C++ 实现如下

// 输入:两个整数a和b的和
// 输出:a与b的和
int add (int a, int b) {// cout << a << " " << b << endl;if (b == 0) return a;return add(a^b, (a&b)<<1);
}

作者想表达计算机的本质是bit的异或、与及移位操作。

思考

这里又是思考:要理解这个加法算法只需要地正确回答出以下三个问题:

  1. a ∧ b 得到的是什么?
  2. (b&a) << 1 得到的是什么?
  3. 该算法为什么会终止?

陆爻齐的回答是,

  1. a ^ b 得到的是 a 和 b 相加后,移位之后且还没计算进位的部分。异或操作是 10 和 01 得 1,11 或 00 得 0,1 与 0 相加,那位不用进位,留 1;而 0 + 0 或 1 + 1,则会在原地留 0,这正好符合异或操作的结果。
  2. (b&a) << 1 得到进位的部分,a&b 的与操作就可以得到 1 + 1 的位,<< 1 是移位操作,根据上文,二进制乘 2,靠后面加个 0, 故向左移一位。
  3. 算法之所以会终止,是因为从右向左,每次执行完进位操作一定能保证该位以右不会有可进位的位,如设第 1 位要进位,那么进位后第一位就确认为 1 或 0,但进位后可能导致下一位需要进位,若此时第二位要进位,那么就处理进位并确认第二位为 1 或 0,以此类推,处理至尽。因处理的数字是有限位数字,故算法一定能终止。

乘法

作者介绍了一种朴素乘法,即 a*b 的本质,是 b 个 a 相加。下面作者以此为例,从正确性、效率、优化三个角度分析该算法。

显然,这种不断加的乘法时间复杂度为O(n)。

然后是重点,递归版的“简单乘法”,C++ 实现如下。

int multiply(int a, int b) {// cout << a << " " << b << endl;if (b == 0) return 0;if (is_even(b)) {return 2 * multiply(a, b >> 1);}else {return 2 * multiply(a, b >> 1) + a;}
}

其实这个程序可以这么理解,返 0 不用说,如果 b 是偶数,比如 0b100 是 8,a 随便取个数,比如 3,即 0b11,用 100 * 11 相当于 2 * (10 * 11),也等于 2 * ( 2 * ( 1 * 11)),最后省个 1,也就加个 a,综上。

换个复杂点的例子,让 b 为 1010,那就可以看为 (12^4 + 02^3 + 12^2 + 02^1) * 3 。

同时作者还补充,在附录 A 有更高效的乘法实现。

除法

定理

首先得有个除法定理,对任意给定的整数 a 和 b,其中 b > 0,存在唯一的整数对 q(商)和 r(余数),使得 a = qb + r 且 0 ≤ r < b。

然后,介绍了下良序原则和单射、满射、一一映射等概念,不过感觉在下面没啥用。

然后是除法的实现,朴素除法与朴素乘法类似,是不断减去除数,至被除数比除数小时,相减次数为“商”,剩下的被除数为“余数”。

简单除法

而简单除法的 C++ 实现如下

std::pair<int, int> m_divide(int a, int b) {// cout << a << " " << b << endl;if (a == 0) {return pair<int, int>(0, 0);}std::pair<int, int> result = m_divide(a >> 1, b);result.first <<= 1; result.second <<= 1;if (a & 1) {result.second += 1;}if (result.second >= b) {result.first += 1;result.second -= b;}return result;
}

某种程度就是那个简单除法的逆运算捏,但我觉得我也不是那么明白,只能感受到,这是在不断对背除数除二,然后从左至右确认“商”,最后消除还不明白如何产生的误差来确认“余数”。

第一章 习题

嘛,又不是正式上课,就选两道做做罢

1 判断奇偶的函数,c语言实现

判断奇数
int func (int a) { if (a & 1) return True; return False; }
判断偶数
int func (int a) { if (a & 1) return False; return True; }

思想是,奇数的二进制表示中,最右位总为 1,只要 & 上 1,就只会保留最右位,1 则奇数,0 则偶数。

2 判断 v 是否为 2 的某次方

两个思路

  1. 若 v 为 2 的某次方,必表现为 100……0 的形式,那么用 while 循环从右至左判断,是否只有最后(最左)为 1 则是;
  2. 若 v 为 2 的某次方,必在减 1 后,为 111……11 的形式,那么用相同位数的 111……11 与之异或,若最后得 0,则是;

小结

CINTA 第一章下来,我想我还是更优先看看 CSAPP 或许更好些,不过其中部分内容真是有意思,从二进制的角度看待加、乘、除,别有一番风味。另外也庆幸不是学校的专业课,不然又是一门备考时令人头疼的科目力

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/741387.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

热爱无限

青春不在年华,而在心境;青春不是桃面、丹唇、柔膝,而是深沉的意志、恢弘的想象、炙热的情感,更是生命中无限的热爱。它使你有一台天线,从天上接受着勇气与力量的信号,使你青春永驻。 怀揣着热爱,我投入到无限的学习之中。当我第一次接触信息学竞赛时,就被其中无限的知识…

Franka Robot 错误处理

使用 FCI 时,您会遇到多种错误,这些错误可能是由于用户发送的不合规命令、通信问题或机器人行为而导致的。以下小节详细介绍了最相关的错误。有关完整列表,请查看 API文档。请注意,发生错误后,您可以自动清除错误并继续使用该franka::Robot::automaticErrorRecovery()命令…

Mybatis Plus 3.X版本的insert填充自增id的IdType.ID_WORKER策略源码分析

总结/朱季谦 某天同事突然问我,你知道Mybatis Plus的insert方法,插入数据后自增id是如何自增的吗? 我愣了一下,脑海里只想到,当在POJO类的id设置一个自增策略后,例如@TableId(value = "id",type = IdType.ID_WORKER)的注解策略时,就能实现在每次数据插入数据库…

共享ip服务器实现外网访问

信息 服务器厂商:炎火云 系统:Windows-2012R2-Datacenter-cn 面板:phpstudy 共享ip服务器实现外网访问思路 通过nat端口映射将内网端口映射到共享ip(即公网ip)端口,实现使用共享ip+端口访问服务器 步骤 首先确定好服务器端口 我这里用的是默认的80端口接着要在防火墙里面…

MySQL-18.主从复制

C-18.主从复制 1.主从复制概述1.1 如何提升数据库并发能力 在实际工作中,我们常常将Redis作为缓存与MySQL配合来使用,当有请求的时候,首先会从缓存中进行查找,如果存在就直接取出。如果不存在再方法数据库,这样就提升了读取的效率,也减少了对后端数据库的访问压力。Redis…

Jetbrains IDE (IntelliJ) 启用原生Wayland支持

启用最新jbr 打开你要设置的IDE,ctrl+shift+a 后输入“runtine”,回车,在显示的窗口中选择jbr21的最新版本,如图所示:设置jvm参数 确认后,点击窗口右下角的小齿轮(如果已经打开了任何项目,先关掉),选择“Edit Custom VM Options“,在出现的文本框最后面加上这么一行:…

30、Django-项目部署-nginx

原理: 安装: 配置: - 这里uwsgi_pass 表示使用uwsgi协议转发代理 - include 表示加载uwsgi协议的参数(固定) - nginx -t   #检查配置文件语法修改uWSGI:socket 表示启用uwsgi协议 本文来自博客园,作者:little小新,转载请注明原文链接:https://www.cnblogs.com/li…

15、 Django-多表操作-多个模块的关联-多对多的增删改查- models.manytomany()

针对多对多的关系django会自动创建第三张表、也可以通过through参数指定第三张表models.py from django.db import models# Create your models here.#多对多 #用户表:电影 = N:M #一个用户可以收藏多部电影 #一部电影可以被不同的用户收藏#电影 class Movie(models.Mode…

14、 Django-多表操作-多个模块的关联-一对多的增删改查- models.ForeignKey()

#多模块关联-- 关联分类:Django中的三个函数-- ForeignKey-称为外键:一对多、将字段定义在多的一端中-- ManyToMnayField:多对多、将字段定义在两端的任意一端中-- OneToOneField:一对一、将字段定义在任意一端中如:一对一:一对多:多对多:常用 如: 模型models.py from …

一文熟悉拖拽式表单设计器的方方面面

通过本文,可以详细了解拖拽式表单设计器的更多优势和特点。很多客户朋友都想知道用什么样的软件平台可以实现提质、降本、增效的目的。可以来了解低代码技术平台、拖拽式表单设计器的更多功能与特点。作为专业的服务商,流辰信息为客户提供整套低代码技术平台服务解决方案,通…

Simple WPF: C# 使用基本的async/await实现异步

本文介绍了基本async/await关键字基于TAP任务异步模型的异步任务处理方法。最新内容优先发布于个人博客:小虎技术分享站,随后逐步搬运到博客园。 创作不易,如果觉得有用请在Github上为博主点亮一颗小星星吧! 博主开始学习编程于11年前,年少时还只会使用cin 和cout ,给单片…

植物大战僵尸1.2.0.1073汉化版

下载链接:https://download.csdn.net/download/hello_hlqk/89528378?spm=1001.2101.3001.9499 植物大战僵尸是一款益智策略类塔防游戏,玩家通过武装多种植物切换不同的功能,快速有效地把僵尸阻挡在入侵的道路上。不同的敌人,不同的玩法构成五种不同的游戏模式,加之黑夜、…