草庐IT

从近世代数的角度理解补码

Az1r 2023-03-28 原文

介绍

模数加法形成了一种数学结构,成为阿贝尔群(Abelian group),这是以丹麦数学家阿贝尔的名字命名的。

前置知识

定义1. 设\(a,b\in Z\),如果存在\(q\in Z\)使得\(a=qb\),则称\(b\)整除\(a\),记为\(b|a\)

定义2. 设\(a,b\in Z\)\(b>0\)\(a=qb+r\)\(q\in Z\)\(0\leq r<b\),则称\(r\)\(a\)除以\(b\)所得到的余数,记为\(a\bmod b\)

定义3. 设\(a,b,n\in Z\)\(n>0\),如果\(a\bmod n=b\bmod n\),则称\(a\)\(b\)\(n\)同余,记为\(a \equiv b\pmod{n}\)

定理1. \(\forall a,b,n\in Z, n>0, a\equiv b\pmod{n}\)等价于\(n|(a-b)\)

定理2.

  1. \(\forall a\in Z, a \equiv a \pmod{n}\)
  2. \(\forall a, b\in Z\),如果\(a\equiv b \pmod{n}\),则\(b\equiv a\pmod{n}\)
  3. \(\forall a,b,c\in Z\),如果\(a\equiv b\pmod{n}\)并且\(b\equiv c\pmod{n}\),则\(a\equiv c\pmod{n}\)
  4. \(\forall a,b,k\in Z\),如果\(a\equiv b\pmod{n}\),则\(a+k\equiv b+k\pmod{n}\)
  5. \(\forall a,b,c,d\in Z\),如果\(a\equiv b\pmod{n}\)并且\(c\equiv d\pmod{n}\),则\(a+c\equiv b+d \pmod{n}\)
  6. \(\forall a,b,k\in Z\),如果\(a\equiv b\pmod{n}\),则\(ak\equiv bk\pmod{n}\)
  7. \(\forall a,b,c,d\in Z\),如果\(a\equiv b\pmod{n}\)并且\(c\equiv d\pmod{n}\),则\(ac\equiv bd \pmod{n}\)
  8. \(\forall a,b\in Z\)\(ab \bmod n=(a\bmod n)(b\bmod n) \bmod n\)

定义4. 设\(n\in Z\)\(n>0\)\(\forall x\in Z\),定义\([x]=\{y|y\equiv x \pmod{n}\}\),称为整数集\(Z\)上在模\(n\)同余的等价关系下的一个等价类。

例.

\(4\)同余关系的所有等价类为:

  • \([0]=\{\cdots,-8,-4,0,4,8,\cdots\}\)
  • \([1]=\{\cdots,-7,-3,1,5,9,\cdots\}\)
  • \([2]=\{\cdots,-6,-2,2,6,10,\cdots\}\)
  • \([3]=\{\cdots,-5,-1,3,7,11,\cdots\}\)

定理3. 设\(n\in Z\)\(n>0\)\(\forall x,y\in Z\)\([x]=[y]\)当且仅当\(x\equiv y\pmod{n}\)

模数加法构成阿贝尔群

  1. \(Z_n=\{[0],[1],\cdots,[n-1]\}\)为整数集\(Z\)上在模\(n\)同余的等价关系下所有等价类之集。
  • \(Z_n\)上定义加法运算“\(+\)”如下:

  • \(\forall [i],[j]\in Z_n,[i]+[j]=[i+j]\),则\((Z_n,+)\)构成一个交换群;

  • \(Z_n\)上定义乘法运算“\(*\)”如下:

  • \(\forall [i],[j]\in Z_n,[i]*[j]=[i*j]\),则\((Z_n,*)\)构成一个交换幺半群。

​ 证明:

  • \(\forall i,j,i',j'\in Z\),如果\([i]=[i']\)\([j]=[j']\),则\([i+j]=[i'+j']\),这验证了“\(+\)”为一个运算。

  • \(\forall i,j,k\in Z\)\(([i]+ [j])+ [k]=[i+j]+ [k]=[(i+j)+k]\)\([i]+ ([j]+ [k])=[i]+ [j+k]=[i+(j+k)]\)\(([i]+ [j])+ [k]=[i]+ ([j]+ [k])\),这验证了加法运算\(+\)满足结合律。

  • \(\forall i\in Z\)\([0]+[i]=[i]+[0]=[i]\),这验证了\([0]\)为单位元。

  • \(\forall i\in Z\)\([n-i]+[i]=[i]+[n-i]=[n]=[0]\),这说明\([i]\)有逆元。

    以上验证了\(Z_n\)对于加法运算“\(+\)”构成一个群。

  1. \(Z'_n=\{0,1,2,\cdots,n-1\}\),在\(Z'_n\)上定义运算"\(\oplus\)"如下:\(i\oplus j=(i+j)\bmod n\),则\((Z'_n,\oplus)\)构成一个群。

​ 证明:

  • \(\forall a,b,c\in Z'_n,(a\oplus b)\oplus c=a\oplus (b\oplus c)\),结合律。

  • \(((a+b)\bmod n+c)\bmod n=(a+(b+c)\bmod n)\bmod n\)

  • \(((a+b)\bmod n+c)\bmod n=(a+b+c)\bmod n\)

  • \((a+(b+c)\bmod n)\bmod n=(a+b+c)\bmod n\)

  • \(0\oplus a = (0+a)\bmod n = a\)

  • 如果\(a\neq 0\),则\((n-a)\oplus a = (n-a+a)\bmod n = 0\)\(0\oplus 0=(0+0)\bmod n=0\)

举例

设用\(n\)个二进制位表示一个整数\(x\)\(x\)的补码定义为:

  • 如果\(x\geq 0\),则\(x\)的补码为\(x\)的原码;

  • 如果\(x < 0\), 则\(x\)的补码为\(x+2^n\)的原码。

1:

设用8个二进制位表示一个整数,计算7-7补码

解:

  • 因为\(7\geq 0\),因此7的补码为7的原码,即7的补码为0000_0111。

  • 因为\(-7 < 0\),因此-7的补码为\(-7+2^8\)的原码,即-7的补码为1111_1001。

\(-7\)的补码还可以这样求解:

  • 先计算7的原码,得到0000_0111
  • 然后取反加1,得到\(-7\)的补码为1111_1001。

例2:

设用8个二进制位表示一个整数,计算-128补码

  • 因为\(-128 < 0\),因此-128的补码为\(-128+2^8\)的原码,即-128的补码为1000_0000。

  • 同样的,\(-128\)的补码还可以这样求解:先计算128的原码,得到1000_0000,然后取反加1,得到\(-128\)的补码为1000_0000。

如果用\(n\)个二进制位表示一个整数,用补码表示的数字的范围为\(-2^{n-1}\sim 2^{n-1}-1\)

对于补码而言:

  • 如果首位为0,其表示的是大于等于0的整数。
  • 如果首位为1,其表示的是负数。

例3

如果用8个二进制位表示一个整数,00001010为哪个整数的补码?10001010为哪个整数的补码?

  • 因为00001010的首位为0,它为一个大于等于0的整数的补码,这个整数为\(10\)
  • 因为10001010的首位为1,它为一个负数的补码,这个负数为\(138-2^8=-118\)

对补码加法的分类讨论

计算机中普遍采用补码表示数字的原因是对于负数的加法可以采用与自然数的加法一样的加法器 。

\(x\)\(y\)为任意的两个整数,分以下4种情况讨论:

\(x\geq 0\)\(y\geq 0\)

  • 此时\(x\)的补码为\(x\)的原码。
  • \(y\)的补码为\(y\)的原码。
  • 按照自然数相加计算得到\(x+y\),恰为\(x+y\)的补码。

\(x < 0\)\(y \geq 0\)

  • 此时\(x\)的补码为\(x+2^n\)的原码。
  • \(y\)的补码为\(y\)的原码。
  • 按照自然数相加计算得到\(x+2^n+y=(x+y)+2^n\)
  • 如果\(x+y<0\),则得到的恰为\(x+y\)的补码;
  • 如果\(x+y\geq0\),计算结果的第\(n\)位(从最右边数起,依次为第0位,第1位,\(\cdots\),第\(n-1\)位,第\(n\)位)会自动抛掉。这恰好就是在\(\bmod 2^n\)

\(x \geq 0\)\(y < 0\)

  • 此时\(x\)的补码为\(x\)的原码。
  • \(y\)的补码为\(y+2^n\)的原码。
  • 按照自然数相加计算得到\(x+(y+2^n)=(x+y)+2^n\)
  • 如果\(x+y<0\),则得到的恰为\(x+y\)的补码;
  • 如果\(x+y\geq0\),计算结果的第\(n\)位会自动抛掉。

\(x < 0\)\(y < 0\)

  • 此时\(x\)的补码为\(x+2^n\)的原码。
  • \(y\)的补码为\(y+2^n\)的原码。
  • 按照自然数相加计算得到\((x+2^n)+(y+2^n)=(x+y)+2^n + 2^n\),计算结果的第\(n\)位会自动抛掉,于是最终得到的计算结果为\((x+y)+2^n\),恰为\(x+y\)的补码。

为什么是取反加一

相信大家一开始学习补码的时候都是记为取反加一,然而在看了本篇博客后,你或许明白了为什么是这样的。

\(x\)为任意一个8位有符号整数(char),也就是说它的二进制位数为8位。

$x \geq 0 $

  • 此时\(x\)的补码为\(x\)的原码。

\(x \lt 0\)

  • \(y = -x\),即\(y\)\(x\)的相反数,y为正数。
  • \(a\)\(y\)的二进制表示(原码),\(b\)\(x\)的二进制表示(补码)。
  • 那么由前面的知识,可以知道,\(a\)\(b\) 在模\(2^n\)(n 为 二进制位数,这里为8)同余运算上,是互为逆元。
  • 那么,\(a\oplus b=(a+b)\bmod 2^n = (e) \bmod 2^n = 0 = (2^n) \bmod 2^n\)
  • 所以,我们可以让\(a + b = 2^n\)。(让\(a + b = 0\)是一样的,原因在下)。
  • 好,现在计算\(b\)
  • 对于一个n位二进制数,\(2^n\) 表示为\(1\_0000\_0000\) ,一共后面为\(n\)个0。(所以在计算机里,这个最高的1是不不存在的,是会被抛弃的,那么也可认为\(a + b = 0\)
  • 现在我们如何凑出这个数?显然,\(a + a' = 1111\_1111\)。(\(a'为对a按位取反, 结果一共n个1\))。
  • 则,\(a + a' + 0000\_0001 = 1111\_1111 + 0000\_0001 = 1\_0000\_0000\)
  • 这时候\(b = a' + 0000\_0001\), 即取反加一。

补码的连续性

现在我们研究下 -1。

  1. 可以根据前面的知识,我们写出\(1\) 的二进制表示(8位)\(0000\_0001\)
  2. 然后取反加一,得\(1111\_1111\)
  3. 现在令\(-1 = e + (- 1) = 0 + (- 1) = 0 - 1\)
  4. 而变为二进制表示后\(0 - 1 = 0000\_0000 - 0000\_0001\)
  5. 在第9位上,可以借1,所以 \(原式 = 1\_0000\_0000 - 0000\_0001 = 1111\_1111\)

补码这样的连续性使得我们在进行有符号数加减法时不需要考虑其他运算规则,直接相加即可。


负权

补码所表示的数,我们通常这样计算:

设表示的数为\(w\) ,二进制数表示为\(s_ns_{n-1}s_{n-2}····s_{2}s_{1},即\)\(s_i (1 \le i \le n)\)\(s_n\)为符号位。

  • 表示负数,\(s_n = 1时\)\(w = 2^{n - 1} * (-1) + \sum_{i=0}^{n - 2} 2^{i}\)
  • 表示非负数,\(s_n = 0时\)\(w = \sum_{i=0}^{n - 2} 2^{i}\)

表示非负数很好理解,就是进制转换

那么负数为什么要有负权呢?为什么最高位代表的权值是负的?

  • 如果最高位我们视为正权,得到的值记为\(w'\)\(w' = \sum_{i=0}^{n - 1} 2^{i}\)
  • 显然,由之前的理论可以知道,\(w' 与 (-w) 互为逆元\)。即\(w’ + (-w) = 2^n = 0 (\bmod 2^n)\)
  • 但是\(w + (-w) = 0 = 0(\bmod 2^n)\)相反数也是互为逆元。
  • 那么它两就是等价类啊。但是它两的二进制表示是一样的,只是计算的方式不一样。
  • 根据等价类的定理3, \([w']=[w]\)当且仅当\(w'\equiv w\pmod{2^n}\)
  • 那么,因为\(w' \gt w\), 则\(w' = w + 2^n\)。则\(w = w' - 2^n\)
  • \(2^n = 2^{n-1} + 2^{n-1}\),也就说我们得减去个最高位的1。
  • 既然这样,令最高位的正权属性变为负权,不就正好是两个吗?
  • 所以,定义最高位为1时,为负权 。

为什么是补码?

现在,让你设计一个正数负数都可以表示的运算系统,你会想到令一位为标志位 (Flag),来特殊地表示这个数是正数还是负数。

那么,计算机科学家们是先想到这样的编程思想(Flag位),还是先由近世代数进一步研究发现的呢?

我认为是由近世代数这样的思想进一步推广研究发现的。

毫无疑问,补码这些性质奠定了计算机科学的基础。


后记

这篇博客主要参考我的近世代数老师的讲义,他在上课时说,他当时在研究生推免答辩就问为什么计算机中要用补码,结果没有人答得上来。

参考资料:王义和.离散数学引论[M].哈尔滨:哈尔滨工业大学出版社,2007

有关从近世代数的角度理解补码的更多相关文章

  1. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  2. TimeSformer:抛弃CNN的Transformer视频理解框架 - 2

    Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图

  3. ruby - 易于初学者理解的 Ruby 库 - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。关闭3年前。Improvethisquestion我正处于学习Ruby的阶段,我想查看一些小型库的源代码以了解它们是如何构建的。我不知道什么是小型图书馆,但希望SO能推荐一些易于理解的图书馆来学习。因此,如果有人知道一两个非常小的库,这是新手Rubyists学习的好例子,请推荐!我想使用Manveru'sInnatelib,因为它试图保持在2000LOC以下,但我还不熟悉其中经常使用的Ruby速记。也许大约100-5

  4. ruby - 无法理解 `puts{}.class` 和 `puts({}.class)` 之间的区别 - 2

    由于匿名block和散列block看起来大致相同。我正在玩它。我做了一些严肃的观察,如下所示:{}.class#=>Hash好的,这很酷。空block被视为Hash。print{}.class#=>NilClassputs{}.class#=>NilClass为什么上面的代码和NilClass一样,下面的代码又显示了Hash?puts({}.class)#Hash#=>nilprint({}.class)#Hash=>nil谁能帮我理解上面发生了什么?我完全不同意@Lindydancer的观点你如何解释下面几行:print{}.class#NilClassprint[].class#A

  5. ruby - 如何理解 Ruby 中的发送者和接收者? - 2

    我很难理解Ruby中sender和receiver的实际含义。它们一般是什么意思?到目前为止,我只是将它们理解为方法调用和获取其返回值的调用。但是,我知道我的理解还远远不够。谁能给我一个Ruby中发送者和接收者的具体解释? 最佳答案 面向对象中的一个核心概念是消息传递和早期概念化,这在很大程度上借鉴了计算的Actor模型。艾伦·凯(AlanKay)创造了面向对象一词并发明了最早的OO语言之一SmallTalk,他拥有voicedregretatusingatermwhichputthefocusonobjectsinsteadofo

  6. ruby-on-rails - Rails - 理解 application.js 和 application.css - 2

    rails新手。只是想了解\assests目录中的这两个文件。例如,application.js文件有如下行://=requirejquery//=requirejquery_ujs//=require_tree.我理解require_tree。只是将所有JS文件添加到当前目录中。根据上下文,我可以看出requirejquery添加了jQuery库。但是它从哪里得到这些jQuery库呢?我没有在我的Assets文件夹中看到任何jquery.js文件——或者直接在我的整个应用程序中没有看到任何jquery.js文件?同样,我正在按照一些说明安装TwitterBootstrap(http:

  7. ruby - 如何将 Thor::Group 注册为带参数的子命令 - 2

    这道题开始于here.但随着我对雷神的了解越来越多,情况发生了很大变化。我正在尝试创建一个带参数的Thor::Group子命令。奇怪的是,如果没有参数,它就可以工作。我可以使用Thor::Group作为子命令吗?这在我输入时有效:foocounterfoo/bin/foomoduleFooclassCLI但是当我输入时这不起作用:foocounter5moduleFooclassCLI','Countupfromtheinput.')endclassCounter:numeric,:desc=>"Thenumbertostartcounting"desc"Prints2numbersb

  8. ruby - 你如何理解 Ruby 中的这个三元条件? - 2

    我在某些代码中遇到了三元组,但我无法理解条件:str.split(/',\s*'/).mapdo|match|match[0]==?,?match:"somestring"end.join我确实理解我是在某些点上拆分字符串并将总结果转换为数组,然后依次处理数组的每个元素。除此之外,我不知道发生了什么。 最佳答案 一种(稍微)不那么令人困惑的写法是:str.split(/',\s*'/).mapdo|match|ifmatch[0]==?,matchelse"somestring"endend.join我认为多行三元语句很糟糕,尤其是

  9. ruby - 您如何将 S3 理解为 Ruby 中的分层目录结构? - 2

    有没有人成功地将S3存储桶读取为子文件夹?文件夹1--子文件夹2----文件3----文件4--文件1--文件2文件夹2--子文件夹3--文件5--文件6我的任务是读取文件夹1。我希望看到子文件夹2、文件1和文件2,但看不到文件3或文件4。现在,因为我将存储桶键限制为prefix=>'folder1/',你仍然会得到file3和4,因为它们在技术上具有folder1前缀。似乎真正做到这一点的唯一方法是吸收folder1下的所有键,然后使用字符串搜索从结果数组中实际排除file3和file4。有没有人有过这方面的经验?我知道像Transmit和Cyber​​duck这样的FTP风格的S3

  10. 关于yolov5训练时参数workers和batch-size的理解 - 2

    关于yolov5训练时参数workers和batch-size的理解yolov5训练命令workers和batch-size参数的理解两个参数的调优总结yolov5训练命令python.\train.py--datamy.yaml--workers8--batch-size32--epochs100yolov5的训练很简单,下载好仓库,装好依赖后,只需自定义一下data目录中的yaml文件就可以了。这里我使用自定义的my.yaml文件,里面就是定义数据集位置和训练种类数和名字。workers和batch-size参数的理解一般训练主要需要调整的参数是这两个:workers指数据装载时cpu所使

随机推荐