为何4个字节int取值范围是-2^31到2^31-1

为何4个字节int取值范围是-2^31到2^31-1
前⾔
最近去参加⾯试,是⼀家还算不错的公司,怎么说呢,因为公司是做⼯具类软件的,电脑端⽹页端⼿机端都有,软件的⽤户量达到了3.5亿之多,由于⾯向⽤户主要是欧美,因此在国内知道的⼈就很少。我⾯试的是iOS岗位,不过⼀开始技术⾯试⼀上来问了我⼀堆计算机基础底层的问题,其中⼀个问题就给我留下深刻的记忆,为啥呢?因为他问我int为4个字节时取值范围是多少,他听到我答案后,斩钉截铁的说我肯定错了,但是呢,这个算是属于计算机的常识问题吧,我从⼤学到现在六七年,⼀直理解的是这个答案,这次⾯试却有⼈态度异常坚决的说我肯定错了。于是,我⾯试完后回家后就好好的在⽹上和书上了答案,果然,我是对的,他是错的。这个给我感触很⼤,让我感觉到,现在⼯作中,应该还有很多他这样的⼈,对⼀个知识的认知是错的,并且还是那么的坚定。因此,我认为,计算机的知识⼀定要知其所以然,不然真的很可能坚持⼀个错误的认知好多年。
正⽂
如果您现在觉得这个问题的答案不是这个的话,那么您就很有必要好好的看下我接下来写的内容了。如果您现在知道是这个答案,但是不知道为啥会是这个值的话,也可以好好看看我接下来写的。如果你已经知道的原因,其实你也可以看看,说不定能对你有更深层次的理解。
解释
刚说的4字节的int默认是在C/C++语⾔中的,并且我们默认说也是有符号的int,也即是包括负数的。
解释这个问题之前,我得先给⼤家说明⼀个⼩知识。众所周知,⼀个字节等于8位(1 byte == 8 bit),为何会有位这个东西呢,原因很简单,这是由于如今⼤家⽤到的计算机CPU以及所有集成电路,都是只能识别电信号的,在这些计算机硬件的眼中,电信号可分为两种,⼀种是⾼电平,⼀种是低电平,⾼电平表⽰1,低电平表⽰0,这就是为啥计算机会只能识别0、1这种⼆进制数的原因了(当然量⼦计算机除外)。在CPU中,接收⾼低电平的硬件叫做管脚,也就是我们常说的⾦⼿指,⼀根管脚能接收⼀个0、1,由于CPU内部的设计,每多⼀根管脚,能表⽰的数值是以指数增长的,也就是如果是16根管脚的话,那么CPU的寻址能⼒就是2^16,同理,32根就是2^32。说到这⼉,⼤家应该也终于是知道了我们常说的位数是啥玩意了吧,没错,就是CPU的管脚数(当然这个仅仅是CPU的位数,操作系统同样也是有位数的,当⼀台电脑的CPU和系统都是64位的是才能真正完全发挥出64位的功效)。
⽆符号
这⾥我们得先好好的说说⽆符号类型,当⼀个⽆符号类型的8位,也就是⼀个字节时,能表⽰的数值个数是多少?是滴,就是2^8,不过呢,我也可以好好的解释下这个,当为⼀位的时候,能表⽰的数值是0和1,也就是2^1,当为2位时,能表⽰的数值是0、1、2和3,也就是2^2,以此类推,8位能表⽰的数
值个数就是2^8,相信你对这个不会有什么异议吧。再来,8位能表⽰的最⼤值是多少?  答案是,2^8 - 1 ,也就是255,这个同样可以解释下,当为⼀位时,最⼤值的⼆进制就是1,也就是⼗进制的1,也就是2^1 - 1,当为2位时,最⼤值的⼆进制是11,也就是⼗进制的3,也就是2^2 - 1,同理,8位时,最⼤值的⼆进制是8个1,也就是1111 1111,算下来的⼗进制数值就是255,也就是2^8 - 1。8位能表⽰的最⼩值想必都知道,就是⼋个0,也就是0。
这样⼦算下来,刚好,从0到2^8 - 1,每⼀个数值唯⼀的对应着相应的⼀个⼆进制值表⽰。这⾥的意思就是,0刚好唯⼀对应着0000 0000这个⼆进制数,255刚好唯⼀对应着1111 1111这个⼆进制数。这样⼦,每个数值都唯⼀对应着⼀个⼆进制数表⽰,所以每个数值都可以很好很和谐的存储着。
有符号傅泽星
有了上⾯对⽆符号的解释,接下来才能好好的给你解释有符号的情况。
所谓的有符号,意思就是,有负数。为啥有负数时,会说成是有符号呢?那我就问你⼀个问题,按照刚刚上⾯对于⽆符号的解释后,你觉得同样是⼀个8位的数值,同样是每个位只能识别0、1的CPU,他到底要怎样才能知道这个⼆进制数表⽰的是正数还是负数呢?前⼈们也想到这个问题了,为了解决这个问题,就引出了⼀条规定,当有负数存在的时候,将最⾼位当做符号位,当符号位为1时,就代表这个数值是个负数,当符号位为0时,就是正数。这就是有符号出现的原因。
为何8位取值范围是-2^7 到2^7- 1
钋元素⾸先我来给⼤家说⼀个错误的答案解释。⼤家现在已经知道了,当有负数的时候,最⾼位是符号位,也就是说,现在这⼋位⾥能真正拿来存储值的位数只剩七位,也就是最⼤值是2^7 - 1再加上符号位的话,也就是,-2^7 - 1到2^7 - 1。⼤家看到这⾥是不是感觉很有道理啊?是不是并感觉不到有错呢?如果你感觉这个很合理的话,你现在的理解就是跟⾯试我的那个⼈的想法差不多了,这可能也是为啥他到现在还那么坚定的认为⾃⼰是对的的原因吧。
其实呢,出现这样⼀个错误的认识,最主要还是归结于⾃⼰没认真去想过这个问题。现在我就给⼤家说下,这样的理解存在⼀个很致命的问题,那就是,0的表⽰,你会发现,当负0时,对应的⼆进制数值是1000 0000,当正0时,对应的⼆进制数值是0000 0000,不知道看到这⼉,你有没看出端倪,⽆论看没看粗来,我都得说粗来,那就是,本来数学上,正0和负0表⽰的是同⼀个数,然鹅在这种情况下,正0和负0表⽰了两个数值,也就是计算机内部⽤了两个⼆进制数来表⽰和存储这两个0,现在是不是觉得恍然⼤悟呢?
原码和补码
前⼈⼤神们为了解决这个问题,就想出了⼀个绝妙的⽅法,那就是补码。说到补码的话,就不得不提到的是原码和反码,为啥要说这两个东西呢,因为补码是通过原码和反码算出来的。前⼈们规定,原科技传播
码就是那个数值直接算出来的⼆进制数,例如,1的原码就是,0000
0001,-1的原码就是,1000 0001。反码呢,就是,除符号位外,其他所有位取反,例如,-1的反码就是,1111 1110。我这⾥为啥不提1的反码呢,因为还有⼀条规定就是,正数的反码和补码都是他的原码,为啥这么规定呢,其实想想都知道原因很简单,那就是,本来正数的⼆进制数表⽰都是⼀⼀对应的,因此就没必要再⼤费周章了,当然,如果不这么规定的话,最终补码的形式也是不会⼀⼀对应⼀个⼆进制数的。
接下来就是补码了,反码算出来了,补码就很简单了,那就是反码加1,例如,-1的补码就是,1111 1110 + 1 = 1111 1111。这⾥提个注意点,就是,在计算补码的时候,最⾼位也是会参与计算的,也就是说,如果反码是1111 1111的话,补码 = 1111 1111 + 1 = 1 0000 0000,这⾥最⾼位1已经超出了⼋位,也就是常说的溢出了,那么就直接忽略了,也就是最终结果是0000 0000,⼤家猜猜这个补码的原码是誰?没错,就是负0,之后再看看正0,我们说过正数的原码、反码和补码都是原码,也就是0000 0000,看见没,这种情况下,正负0都是同⼀个⼆进制表⽰。这就已经很好的解决了0的问题。
冲突解决
这⾥就开始好好的跟⼤家说说这个取值范围。
⾸先,先说⼀⼀对应的事,⼤家已经知道了,当有负数存在的情况下,最⾼位是符号位,之后再根据原码、反码和补码的⼀系列规定和计算,有⼀点是可以确定的,那就是,负数和正数的⼆进制表⽰绝对不可能冲突,意思就是不会存在⼀个负数的⼆进制表⽰和某个正数的⼆进制表⽰是⼀样的,就是因为,负数补码的最⾼位永远是1,正数补码的最⾼位永远是0,能让负数补码最⾼位为0的情况,只有⼀种,那就是0的时候。为0时刚好就解决了正负数存储时正负0⼆进制表⽰不⼀致的问题,这也是补码的⼀个作⽤之⼀。之后就是正数的⼀⼀对应,之前也说过,正数情况下,补码就是原码,所以正数是肯定不可能存在正数之间的数值冲突的。最后再说负数,由于,原码时,每个⼆进制都是⼀⼀对应的(跟正数同理),那么负数的所有反码也都是肯定⼀⼀对应的,如果⼤家理解不了,可以⾃⼰试试⽤⼆进制看看,你会发现,⽆论是原码还是反码,每个数值的表⽰,肯定⾄少有⼀位跟其它任何数值都不⼀样,这就证明的唯⼀性。既然原码、反码都具有唯⼀性了,那么再加上⼀个1的话,仍然具有唯⼀性。
爆炸力学有符号8位的取值范围
费劲千⾟万苦,终于来到了这⾥。⾸先,我们这⾥再回顾⼀下,就是,当存在符号位时,8位能表⽰的最⼤值就是111 1111,也就是7个1,也就是2^7 -1, 所以正数的范围就是0到2^7 - 1,负数就是-2^7 - 1 到-1,但是,这样算下来的话,总共表⽰的数值个数是2^7 +
钢窗料
2^7 - 1 = 2^8 -1,这可是⽐8位能存储的2^8这个数值少⼀个呢,这样不就活⽣⽣的浪费了⼀个麽?不
人员定位系统
知⼤伙有没注意到⼀个情况,那就是当为负数时,补码是1000 0000时,我们通过这个补码反向算得反码是0111 1111,原码就是0000 0000是不是感觉很诡异,这不是正0吗?⾔下之意就是说,补码1000 0000这个⼆进制位压根不可能有,这就是刚说的存储⼆进制位中少的那个。但是呢,由于1000 0000本⾝代表的是128,再加上最⾼位为1,那么就是个负数,再加上所有的⼆进制表⽰⼜少了⼀个,因此,1000 0000就顺理成章的成了-128,当然,1000 0000是补码,它没有原码和反码。最后再加上⼀个计算机内部对负数的运算⽅式吧,就是对负数整体取绝对值,之后取反加1,算下来就是:-128(取绝对值) -> 128(变成⼆进制表⽰) ->1000 0000(取反)->0111 1111(加1) -> 1000 0000(补码)。-127(取绝对值)->127(变成⼆进制表⽰)->0111 1111(取反)->1000 0000(加1)->1000 0001(补码)。-126(取绝对值)->126(变成⼆进制表⽰)->0111 1110(取反)->1000 0001(加1)->1000 0010(补码)。你会发现,计算机内部对负数补码的运算的结果和我们之前说的运算结果是⼀⽑⼀样的,从这⾥也就能清楚的看到,-128通过计算机内部运算之后的补码就是1000 0000
为何4个字节int取值范围是-2^31 到2^31 - 1
这⾥⼤伙应该就能清楚明⽩的知道为何4个字节int取值范围是-2^31 到2^31 - 1了吧。

本文发布于:2024-09-20 21:20:35,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/683580.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:补码   负数   问题   正数   符号   数值
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议