首页 > 资讯攻略 > 游戏问答

10进制数怎么表示看这里!计算机中数字进制数的表示

文章来源:互联网整理作者:招财猫手游网发布时间:2023-10-26 15:31:48

今天我们讨论了最基本的问题之一:进入。

我们平时使用的自然数是小数,计算机使用二进制运算,使用二进制是因为电子元件只能以高低电压的两种状态组合和计算,所以决定了二进制可以成为现代计算机的基础。

为了方便表示,人们还经常会使用八进制和十六进制来记录二进制数。关于数的进位制,例如N位制,常见的一种观点是,低位满N,就向高位进一。除了这种理解之外,我们这里再讨论一种更有用的理解。那就是将数字的每一位赋予一个权重,一个数字的真实值就是每一位上的数字乘以这一位所对应的权重,然后再加起来。例如,对于一个十进制数,个数的权重是1 = 10^0,十位的权重是10^1,百位的权重是10^2,依次类推,那么,一个十进制数1368就可以表示为

同样,一个二进制数可以表达为

这个分解式看wwW.MuwuyA.CO+M起来很简单,但意义却很重大,这使得我们从“满几进一”的思维中跳出来,可以重新定义每个位的权重。比如在普通的十进制数中,十位的权重是10,百位的权重是100,但是,我们可以根据需要,规定十位是十进制,百位是八进制的,也就是说,十位的权重仍然是10,百位的权重变成了8∗10 = 80。(这句话务必看明白,我们创造了新的混合进制数。在后面的文章里我会介绍递增进位制,这种进位制的每一位都不相同,但它却是编码状态,进行组合计数等等的基础,如果不理解进位制的话,那么这种技巧在你看来可能就是很难想到的淫巧奇技,但是在进制分析法面前,这种技巧毫无秘密可言。)

计算机中数字的表示

计算机中是如何表示一个整数的,一个负数呢?一个浮点数呢?搞清楚这个问题有多重要,我来举个例子。曾经有一位网络游戏的服务端同学,在写角色身上的金钱的时候,使用了int型,但在程序的其他地方,却又使用了unsign int来存储,更不幸的是,在扣玩家身上的金钱的地方,又出现了并发的情况,导致金钱会出现负数。一个整型负数,转成无符号整型的时候,悲剧就发生了:玩家变得巨有钱。一个刷金的BUG就这样产生了。要搞明白这个问题,就得先搞明白,在计算机中,每个数是怎么表示的。还有,比如,这样一个BUG,有一次,我发现从网络接收的数据不对,只好把接到的数字一个字节一个字节地去分析,最后发现,发送方发送了一个浮点型,而接受方却是以整型去解释的。那么浮点型的1.0和整数的1到底有什么不同呢?(这还是原始时代的BUG,感谢protobuf,netty,我们再也不用担心应用层网络消息的格式了。)

我们都知道Java中的byte类型是一个字节,8位,short是两个字节,16位,int是四个字节,32位,long是8字节,64位。为了方便描述,我们以byte为例,一个字节,8位能表达的范围是从(00000000)2 ~ (11111111)2,转成十进制,就是从0到255。但书上告诉我们,byte能表达的范围是-128~127。这就牵扯到了负数的表达了。在计算机里,对于有符号的数据类型,会把最高位做为符号位,如果为1,则为负数。我们可以测试一下。

int i = 1;A((a << 30) > 0);A((a << 31) < 0);A((a << 31), In);

看,如果我们把1左移31位,也就是送到了最高位上,这个数就变成了int型所能表示的最小值了。

由于32位整数写起来太罗嗦了,我们先只以byte的情况进行分析。负数通常有三种表示方法。第一种,把符号位设为1,后面的数字等于这个负数的绝对值,例如-15就变成了10001111。这种方法称为原码。还有一种,保持符号位不变,后面的数字全部取反,例如-15就变成了11110000,这种方法称为反码。最后一种,称为补码,它是由反码加1得到的。例如,-1的反码是11111110,再加1就是11111111。使用补码的好处包括,0和-0的表示是相同的,正负数可以直接进行加减法运算,不必再做额外的转换。而原码和反码则不具备这样的优点。所以现代计算机都是使用补码来表示负数。

递增进位制数

递增进位制数是这样一种数,它的最右一位(称为个位已经不太准确了,我们使用左右来代替个位十位的称呼)是二进制的,它的右数第二位是三进制的,右数第三位是四进制的 ……它的右数第N是N + 1进制的。用权重的观点来看,它的最右一位的权重是1,右数第二位的权重是1∗2 = 2!,右数第三位的权重是1∗2∗3 = 3!,右数第N的权重是N!。 我们也用上面的方法来表示递增进位制数:

递增进位制数的最常见的一个作用就是用来编码全排列。通过递增进位制数,我们可以建立N个元素的全排列与自然数[1,N!]的一一对应关系。在下一节,生成全排列那里,我们会进行详细地讲解。

好了,看完上面的内容,可以尝试实现下下面的题目:

    写一个程序,输入是一个十进制整数,输出是它的二进制表示的字符串。函数原型 String oct2Bin(int a),例如,输入8,返回值是“1000”。要考虑负数哦。写一个程序,进行数制的相互转换,原型是String transform(String s, int radixSrc, int radixTgt),其中,s代表原始的字符串,radixA代表源进制,radixB代表目标进制。例如transform("221", 3, 2),返回“11001”。因为3进制的221,就是十进制的25,而十进制的25就是二进制的11001。同理,transform("11001", 2, 3)返回值就是“221”。自己查一下float和double在计算机内是以什么格式输出的,并思考,如果在网络上只能以字节流的方式传送,这些数字应该怎么办?(例如,InputStream/OutputStream都只能处理字节流。)猜想一下以下代码的运行结果是什么?并写程序验证,体验一下数据溢出。
short a = By; int b = S; short c = By + 1; byte d = (byte)(By + 1);

文章来自知乎专栏:

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表本站立场。文章及其配图仅供学习分享之用,如有内容图片侵权或者其他问题,请联系本站作侵删。