大家好,我是Hululu。我们都知道,现代计算机都是用0和1组成的二进制数来表示所有的信息。那你是不是有时会有这样的疑问:为什么计算机要用二进制?二进制如何表示计算机相关信息?例如数字、字符串、声音、图片、视频等。十六进制计算是一种常见的计算方式。常见的有十进制、二进制和十六进制。组成,不能从0开始,每个小数都是1。小数是我们从小就潜移默化地学到的东西。我们大多数人的手指或脚趾的数量是10,这自然使我们适合以十进制为基础的数字系统二进制。数字中只有0和1。,数字0-7,每八进制十六进制,数字分别为0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,由F组成,每十六合一。它的表达形式比较特殊,因为10~15不能用数字表示,所以强制要求:10用A表示,11用B表示,12用C表示,13用D表示,14用E,15用F表示。系统间转换R-base→Decimal:按权重展开Decimal→R-base:整数和小数分开处理。整数部分的转换方法是:“除底取余,右上左下”。即以R为底数除以待转换的十进制整数,取余数作为结果数据中每一位的编号,直到余数为0。将上面的余数(先求得)作为上位右低位,下面的余数作为左高位的数位。小数部分的换算方法是:“乘以底数向上、上、左、下、右四舍五入”。即用待转换的小数与基数R相乘,乘积的整数部分作为结果数据中每一位的数,继续将小数部分与基数R相乘。以此类推,直到某步乘积的小数部分为0或者已经得到想要的位数。最后将高位整数部分作为左边高位的数字,低位整数部分作为右边低位的数字。需要注意的是:在转换过程中,乘积的小数部分不一定总是为0,即转换成想要的位数后有余数。在这种情况下,获得的值是近似值。将二进制转换为八进制和十六进制是因为二进制的三位整体被认为是一个八进制数,而二进制的四位也是一个十六进制数。通过这个规则,我们可以轻松实现二进制、八进制、十六进制之间的转换。整数部分从低位到高位每3、4位用一个等效的八进制/十六进制数代替,高位不足时补0;小数部分从高位到低位每3位或4位换成等值的8或10替换16进制数,不足时,低位补0,八进制,16进制转二进制,每一位换成等值的3或4位二进制数,整数部分高位0省略;小数部分的低位0被省略。为什么计算机使用二进制??我们从小就比较熟悉十进制运算。0、1、2、3、4、5、6、7、8、9这十个数,每十一个。但是计算机使用二进制,只有0和1两个数字,每个二进制都等于1。使用二进制的原因:二进制是自然界中最容易表达的。自然界中有许多二进制系统。电压的高低、水位的高低、门的开闭、电流的有无等等,都可以构成一个二进制系统。计算机使用与现代计算机系统的硬件实现相关的二进制。制造两个稳定的物理设备很容易,以至于组成计算机系统的逻辑电路通常只有两种状态,即开关的开和关。由于每一位数据只有关和开两种状态,二进制数据表示具有抗干扰能力强、可靠性高的优点。二进制非常适合逻辑运算,可以很方便地用逻辑电路实现算术运算。机器号和真值机器号一个数在计算机中的二进制表示称为机器号或该数的机器码。因为我们平时用的不仅是正数,还有很多负数,而计算机不能识别符号“+”和“-”,所以计算机规定二进制数的最高位为0代表一个正数数,如果为1,则表示负数。机器号已签名。如果十进制数是+3,计算机字长是8位,机器码转成二进制是00000011。如果为-3,则表示符号位为10000011的机器号对应的真实值就是该机器号的真实值。我们知道机器号的第一位是符号位,比如10000011直接转换成十进制就是131,但实际上最高位1是一个负号,它的真实值是[-3]什么是机器号的编码形式?原码原码是符号位的绝对值加上真值,即用最高位表示符号,其余位表示值。例如,如果是8位二进制:[+1]=(00000001)original[-1]=(10000001)根据二进制的规则,我们人类可以将原码表示的数理解为一目了然,方便人类提出一个经典问题:8位二进制数的原码取值范围是多少?我们只需要将表示符号的最高位以外的位,即[11111111,01111111]转换成十进制:[-127,127]n位二进制数呢?取值范围:image-20221129211701296现在看起来很漂亮,但是我们在正数和负数相加的时候遇到一个问题:2[+1]的减法其实相当于[+1]和[-1]相加,我们的期望是0,但是当计算机实际计算出来的时候:(00000001)original+(10000001)original=(10000010)original=[-2]为了解决这个问题,inverse反码就应运而生了。反码主要针对负数。正数的反码是自己,负数的反码是根据原码。符号位不变,其他位取反[+1]=(00000001)original=(00000001)inverse[-1]=(10000001)original=(11111110)如果反码反码为正number,那么我们还是可以一眼就知道它的值,但是如果是负数的倒数,我们就需要将它转换成原码才能看到它的真实值。如果最高位有进位,则送回最低位加(循环进位)[-1]=(10000001)原=(11111110)反[+7]=(00000111)原=(00000111)reverse[-1]+[+7]=(11111110)reverse+(00000111)reverse=(100000101)reverse=(00000110)reverse=[+6]2正相减法:[+1]-[+1]=[+1]+[-1]=(00000001)reverse+(11111110)reverse=(11111111)reverse=(10000000)original=[-0]这是一个完美的实现”加法ofpositiveandnegativeisequalto0",但奇怪的是这个[-0]是有符号的,这是由于原代码设计之初的问题,(10000000)original=[-0](00000000)original=[+0]是的,你没有看错,其实就是两个零,习惯了电脑里所有东西的一一对应,严谨认真的工程师表示不能接受,他们不得不想办法去掉[-0],最后他们发现了补码的神奇法则complement和complementcomplement:继续改进负数的思路:正数的补集就是它自己。负数的补码以原码为基础,符号位不变,其余位取反,最后一位+1。即在反码的基础上,最后一位+1[+1]=(00000001)original=(00000001)reverse=(00000001)complement[-1]=(10000001)original=(11111110)reverse=(11111111)Complement[+1]-[+1]=[+1]+[-1]=(00000001)Complement+(11111111)Complement=(100000000)Complement=(00000000)Complement=[0]如果补码补1时最高位进位,则最高位自动丢失。期间引用了计算机对符号位的自动处理,利用自动舍弃最高位来实现符号的自然处理。那(10000000)补现在是什么意思呢?-128(10000000)补码=-1*2^7=[-128](1011)补码=-1*2^3+02^2+12^1+1*2^0=-5(0011)补码=0*2^3+02^2+12^1+1*2^0=3如果是8位二进制,则原码或反码表示的范围是[-127,+127],而补码用表示的范围是[-128,127],补码也可以表示一个最小数。补码其实是脱胎于模块化操作系统:比如一天24小时就是模块化操作系统,任意时刻的小时数都是023到23之间的一个整数,类似于今天的24指向24点,即明天0:00;今天25:00是明天凌晨1:00;今天-4点是昨天20:00。据说20是-4对24取模的补码,取模是容量和极值的意思。又如:时钟上的12个刻度也是一个模数计算系统。假设时钟现在指向10,要将指针移动到6,有两种方法可以反转4个空格:10-4=6和转发8个空格:10+8=18=6(mod12),所以-4在模12系统=8(mod12)中,我们称8为-4对模12的补码在模运算系统中:负数可以用其正补码(负数的补码)代替,并且负数的补码=模-负数的绝对值就是我们前面公式中负数的补码=符号位不变,其余位取反,最后一位+1。它是怎么来的?把负数的原码倒过来加1,这个只是大家记住的一种手段。其实相当于加上一个模256,就是2^8。为什么需要拆除它?这是因为8位机和8位二进制数,只能表示0~255个数,一共256个数,所以不能表示256的值,只能是255+1。既然计算机系统中既有正数也有负数,那应该怎么表示呢?电脑高手想到了。256个数可以一分为二,最高位指定为符号位。最高位以1开头表示负数,最高位以0开头表示正数。这里需要注意一下,特殊的0,所以8位二进制数的范围变成了[-128,127],这个范围是不是很眼熟啊![-1]=(10000001)original=(11111110)inverse=(11111111)complement,如果符号位参与计算,则(11111111)补码的小数点等于255。而255+|-1|=256,也就是模数。补码是天生的东西,机缘巧合下是一把好手。总结:补码不仅仅解决了[-0]的问题,核心是让计算机做减法,转为加法。A-B=A+B的补码使用补码将减法运算变成加法运算,这样在硬件上只需要一个加法器,不需要其他硬件,降低了电路的复杂度。使用补码不浪费编码数,存储空间利用率高补码可以用n&0判断负数的奇偶性,所以计算机底层使用二进制数来存储数据,但是计算机在存储一个数的时候,它不直接存储数字对应的二进制数,而是存储数字。数字对应于二进制数的补定点数和浮点数。定点数的意思是:即约定所有数据的小数点在机器中的位置是固定的。定点数据通常表示为纯小数或纯整数。为了用纯小数来表示数字,小数点通常固定在数字部分的最高位之前;并且为了将数字表示为纯整数,小数点固定在数字部分的末尾。面条。例如:25.125的整数部分在十进制中:25用二进制表示为:11001小数部分:0.125用二进制表示为:。点数、浮点数和定点数表示的缺点是形式过于死板。小数点的固定位置决定了固定位数的整数部分和小数部分,不利于同时表示特别大或特别小的数。归根结底,大多数现代计算机系统都采用了浮点数的表达方式,即用科学记数法来表达实数,即尾数(Mantissa,尾数有时也被称为有效数,实际上是对一个数的非正式称呼。有效数)、基数(Base)、指数(Exponent)和表示正负的符号来表示实数。例如:352.47=3.5247*10的2次方178.125转为二进制为10110010.001,可表示为:1.0110010001乘以2的111次方(111是7的二进制表示)123.45可表示为1.2345x10十进制科学计数法的2次方,其中1.2345是尾数,10是底数,2是指数。浮点数利用指数来达到浮动小数点的效果,从而可以灵活地表示更大范围的实数。字符串编码ASCII码在计算机中,不仅数值可以用二进制表示,字符串也可以用二进制表示。上个世纪,美国制定了一套字符编码,在英文字符和二进制数字的关系中加入数字和一些特殊符号,然后用8位二进制来表示我们日常需要的所有字符。这就是我们常说的ASCII码ASCII码就像一本字典,二进制和字符一一对应。其中,我们来看几个典型的例子:小写字母a在ASCII中,十进制为97,即二进制为01100001,大写字母A,十进制为65,对应二进制为01000001.需要注意的是,里面的数字,比如数字1,二进制对应的是00000001,在ASCII中,其实代表的是字符“1”,对应的二进制是00110001,字符串15并不是用00001111的8位二进制,但是变成了两个字符1和5连续放在一起,即00110001和00110101,需要用两个8位二进制数来表示。所以计算机存储数据的时候,二进制序列化比直接存储文本可以节省很多空间EASCII:ExtendedASCII最开始美国写了ASCII表,英文是用128个符号编码的,但是随着计算机的普及,西欧国家不完整。是英语国家,有德语、法语等。比如字母上面有注音符号,就不能用ASCII码表示。于是欧洲的工程师决定使用字节中最空闲的位来编写新的符号。他们把ASCII扩展变成了EASCII,其中包括希腊字母、特殊拉丁符号等。由于ASCII只占7位,所以EASCII用第8位用一个字节来表示,此时表示的字符数是256个。Unicode但EASCII没有成功。西欧国家和各个PC制造商创造了许多不同的编码字符集。ISO-8859将西欧国家的编码一并收录。但随着电脑来到中国,欧美那些国家现有的字典已经用光了,汉字有十万多个,急需一部新的??“字典”。GB2312编码出来了,用两个字节表示一个汉字(汉字太多),所以理论上最多可以表示256x256=65536个符号。后来GBK编码加入了古汉字等生僻字。台湾地区创造了BIG5码,然后GB18030统一了东南亚的文字。简单了解这些代码后,就不具体说了。后来,计算机在世界范围内流行起来。各个国家和地区的文字编码太多了,Unicode编码的出现就是为了统一世界上所有的文字。Unicode是一个大集合,今天可以容纳超过100万个符号。由于Unicode只是一个字符集(Charset),它只规定了符号的二进制编码,而没有规定二进制编码应该如何存储,即字符编码(CharacterEncoding),这使得计算机无法区分Unicode和ASCII,比如三个一个字节代表一个符号,而不是分别代表三个符号呢?随着Internet的兴起,UTF-8是Internet上使用最广泛的Unicode实现。UTF-8是一种变长编码。它可以用1~4个字节来表示一个符号,字节长度根据不同的符号而不同。Unicode字符集中的大多数汉字如果用UTF-8编码占用3个字节。我们来看看UTF-8是如何兼容Unicode的:UTF-8编码致力于统一世界上所有的字符集,所以它的设计不仅要向后兼容ASCII编码,还要考虑可扩展性。规则如下:1)对于单字节符号:字节的第一位设为0,后7位为该符号的Unicode编码。同ASCII编码规则;2)对于n字节符号(n>1):第一个字节的前n位全部置1,第n+1位置0,后面字节的前两位始终置10其余未提及的二进制位均为该符号的Unicode编码。UnicodeUTF-8byte数0000~007F0XXXXXXX10080~07FF110XXXXX10XXXXXX20800~FFFF1110XXXX10XXXXXX10XXXXXX310000~1FFFFF11110XXX10XXXXXX10XXXXXX10XXXXXX4我们可以发现,UTF-8编码的第一位如果是0,则只有一个字节和ASCII编码完全一样,所以是兼容的。如果以110开头就是两个字节,以此类推如上表。所以前几位的值就是代码本身,同时也是后续判断字节数的推送代码(通过推送代码可以判断有几个该字节之后共同参与表示一个字符的字节)乱码编码是将数据从一种形式转换为另一种形式的过程,而解码是编码的逆过程。编码是一种格式,解码是另一种格式,当然也可能出错。我们举个例子来看看这个问题:创建一个hello.txt文件,用Notepad++打开编辑,把hello写成UTF-8格式,然后我们把Notepad++的formaat格式改成GB2312,然后hello就变成了UTF-8字典,hello这两个词的十六进制编码分别是E4BDA0和E5A5BD。在GB2312字典中,这三个字符的十六进制编码分别为E4BD和A0E5。、A5BD由于UTF-8编码的汉字是3字节,GB2312编码的汉字是2字节。电脑用GB2312解析UTF-8,3个字节硬生生分成2个字节。一组去解码,所以才会出现这样的乱码。当我们知道了乱码的原因后,如何解决就变得很简单了。com/question/20159860https://blog.csdn.net/f919976711/article/details/116714860本文转载自微信公众号“小牛葫芦露”,作者“小牛葫芦露”,可通过以下二维码关注代码。转载请联系“小牛呼噜噜”公众号。
