byte类型的取值为什么是-128~127
参考:https://blog.csdn.net/qq_22771739/article/details/84496115
https://blog.csdn.net/boatalways/article/details/17027573
https://blog.csdn.net/zhiwen_a/article/details/81192087
Java的byte类型取值范围是-128~127为什么负数是128正数到127呢
首先需要了解原码反码和补码
正数的原码反码补码是一样的
[+2]=[00000010]原=[00000010]反=[00000010]补
对于负数来说,它的原码反码补码就不相同
[-2]=[10000010]原=[11111101]反=[11111110]补
最高位表示符号位0代表正数1代表负数,负数计算反码的规则是符号位不变,其余位取反即1变成0,0变成1,补码就是反码再加1
为什么要设计出反码和补码
因为计算机只有加法没有,减法,在做减法运算的时候,可以认为是加上一个负数,这样可以减少计算机电路的复杂度
使用原码进行减法运算会出现问题,例如计算1-1,因为计算机没有加法只有减法,所以计算机自动换算成1+(-1)
1-1=1+(-1)=[00000001]原+[10000001]原=[10000010]原=-2 (符号位也参与运算)
而1-1的实际结果是0
为了解决这个问题,于是使用反码运算
1-1=1+(-1)=[00000001]原+[10000001]原=[00000001]反+[11111110]反=[11111111]反=[10000000]原=-0
通过反码计算的结果是11111111在计算一次反就成原码了,得出的结果是正确的,但是有一个问题是 00000000可以代表+0 10000000可以代表-0,其实是一样的,用2个编码实在是浪费。于是出现了补码解决0的符号以及两个编码的问题
1-1=1+(-1)=[00000001]原+[10000001]原=[00000001]补+[11111111]补=[00000000]补=[00000000]原
这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128:但是注意因为实际上是使用以前的-0的补码来表示-128, 所以-128并没有原码和反码表示.(对-128的补码表示[1000 0000]补算出来的原码是[0000 0000]原, 这是不正确的)
使用补码,不仅仅修复了0的符号以及存在两个编码的问题,而且还能够多表示一个最低数。这就是为什么8位二进制,使用原码或者反码表示的范围是[-127~127],而使用补码表示的范围为[-128~127]
总结:反码是为了解决减法运算,补码是为了解决反码产生的+-0的问题
下面来分析为什么byte型的取值范围为什么是-128~127
1,byte占用8位,每位用0或者1表示,能够表示258(2^8)个数据
2,这8位分为符号位(最高位)和数值位(剩余七位),符号位0表示正数,1表示负数。
3,按上一步的理解,容易得到(+127:0111 1111、+1:0000 0001、+0:0000 0000、-0:1000 0000、-1:1000 0001、-127:1111 1111),计算机底层定义了+0(0000 0000)就是0,那么“可怜的-0”又该何去何从呢?计算机遇到这个二进制该如何处理呢?总不能把这两个都对应0吧,这显然是资源浪费。
4,到这里我们都认为最高位是不参与计算数值的,仅仅是一个符号位,按这种思路byte的八位是无论如何也表示不出-128。而“可怜的-0”又不知道自己代表谁,不得而知“可怜的-0”就是-128。(为什么呢?凭什么呢?你说代表-128就代表-128呀!为什么不能是+128、-250、+250.......)。
5,到这里我们已经很粗浅地回答了-128~127中的-128的由来,基本也回答了这个题目。
6,可是然而但是——对于程序员来说,上诉的分析【首先】是结论正确,但是过程错了。错误在于——负数的二进制表示是错误的,比如-127:1111 1111,这是不对的。计算机发现了1111 1111会把它认为是-1而不是-127。【其次】没有解释为什么-0最后表示成-128。
7,计算机基础知识补充
<1>计算机存储有符号的整数是都是存储它们的补码。Java语言都是有符号位的。
<2>正数和0的补码、反码是本身原码;所以对于正数来说,可以理解为不存在反码和补码。
<3>负数的反码是是符号位不变,其它位取反;补码是在负数的基础上加1(符号位不变)。负数就是矫情啊!
<4>计算机中用补码进行加法运算。
8,接着从人的思考方式理解下当计算机处理1111 1111的过程,首位是1,自然是负数,而且这是补码,那么对应的原码就是,先减1,变成1111 1110,符号位不变,其他取反,变成1000 0001,也就是-1!所以从10000001到11111111依次表示-127到-1
9,最后来解决这-128为什么可以用100000000表示
这里我分析的是byte,它就8位。在无符号位的二进制中128的表示为1000 0000。有符号位的情况下byte好像无法表示+128或-128。
如果我们假设byte不是占用8位,而是9位,最高位是符号位。你们-128的表示为1 10000 0000,计算其补码也是1 1000 0000,很神奇吧,一样的。-128补码尾8位就是1000 0000。那就规定1000 0000是-128的补码,而-128是没有原码和反码的,即不能利用10000 0000反推其反码和原码。
10,如果你对9步的推导表示不太接受,那么简单就认为计算机规定了1000 0000就是-128,是一种人为设计没有什么道理可以言(据说是印度阿三设计的)。其实这么设计也是很巧妙的,在于:
【其一】对于如果大于8位的有符号整数数据类型,-128的补码尾八位刚好是1000 0000
【其二】比如127(0111 1111)加1(0000 0001)刚好得到-128(1000 0000),-128(1000 0000)加1(0000 00001)等于-127(1000 0001)这样从-128~127的反码首尾相连,形成了一个闭环,就像时钟一样。
【其三】在计算机中减法运算可以转换成加法运算,比如8-1——>8+(-1)——>补码运算:(0000 1000) + (1111 1111) = (0000 0111) 刚好是7。-128+127——>(1000 0000) + (0111 1111) = (1111 1111)刚好是-1,-128的补码完美的适用于减法。
结论
【1】计算机中负数是用补码的形式保存、并用它参与加减法运算的,减法会被转换为加法,计算机中没有加法运算。
【2】反码是为了解决减法运算,补码是为了解决反码产生的±0的问题。参考(https://blog.csdn.net/boatalways/article/details/17027573)
【3】对人而言二进制所代表的值一定是从原码求出的,开头如果是1的二进制,一定要说明其实原码、反码还是补码。
【4】在原码、反码、补码相互转换以及求对应的十进制求值时,符号位是绝不参与的,但是在加减过程中,是参与位运算的。
【5】计算机中规定了-0对应的二进制就是0,那么-0就没有意义了,必须找一个数和它对应。
【6】byte的最小值-128、short的最小值-32768、int的最小值-2147483648都是用对应的-0的原码来进行表示,这是人为规定的、人为规定的、人为规定的。但是这么规定又很巧妙,妙在上述10中的三点。
byte类型的取值为什么是-128~127的更多相关文章
- 为什么Java byte 类型的取值范围是-128~127 (转)
概念:负数的补码是该 数 绝 对 值 的 原 码 按 位 取 反 ,然 后 对 整个数 加 1 步骤: 1.确定byte是1个字节,也就是8位 2.最大的应该是0111 1111,因为第一位是符号位, ...
- 关于JAVA中Byte类型的取值范围的推论(*零为正数,-128在计算机中的表示方法...)
先看一段推理<*一切都是在8个比特位的前提下,讨论二进制的符号位,溢出等等,才有意义*> +124:0111 1100 -124:1000 0100 +125:0111 1101 -125 ...
- byte的取值范围是-128~127,那么包含-128和127吗?
本帖最后由 王德升老师 于 2019-12-27 17:56 编辑 byte的取值范围为什么是-128~127?如果面试官问你取值范围包含127吗?1. 首先我们知道Java中byte类型是1个字节占 ...
- GO语言学习笔记2-int类型的取值范围
相比于C/C++语言的int类型,GO语言提供了多种int类型可供选择,有int8.int16.int32.int64.int.uint8.uint16.uint32.uint64.uint. 1.i ...
- java中为什么byte的取值范围是-128到+127
概念:java中用补码表示二进制数,补码的最高位是符号位,最高位为“0”表示正数,最高位为“1”表示负数.正数补码为其本身:负数补码为其绝对值各位取反加1:例如:+21,其二进制表示形式是000101 ...
- c c++各种类型的取值范围
int类型的变量存储值从-2147483648到2147483647 //例子 #include <iostream> using namespace std; int main(void ...
- 为什么byte的取值范围是-128到127
一个byte由八个位组成,如00000000,其中,符号位+数值位,前7位表示数值,第8位是符号位(0为正,1为负).这样+1就是00000001,-1就是10000001.最大的正数就是0 1111 ...
- loadrunner:参数类型及其取值机制
参数类型 参数名随意取,建议取通俗易懂的名字,下面我们重点介绍一下参数的类型. ●DateTime: 很简单, 在需要输入日期/时间的地方, 可以用DateTime 类型来替代. 其属性设置也很简单, ...
- easyui radio 类型的取值和赋值方法
1.HTML 文件 <tr id="client_check1"> <th>委托人证件类型:</th> <td><input ...
随机推荐
- 异常错误:在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式
最近做一个蛋疼的东西就是C#调用windows API 来操作一个摄像头,自动处理一些东西.要用到剪切板复制 粘贴功能,即 Clipboard.SetDataObject(filedic, true) ...
- 用mingw32编译ffmpeg2.7
1. 下载x265最新源码: 下载ffmpeg源码(我用的是2.7): 下载cmake最新版本并安装: 下载SDL(我用的SDL-1.2.15): 下载min ...
- 项目Alpha冲刺--9/10
项目Alpha冲刺--9/10 作业要求 这个作业属于哪个课程 软件工程1916-W(福州大学) 这个作业要求在哪里 项目Alpha冲刺 团队名称 基于云的胜利冲锋队 项目名称 云评:高校学生成绩综合 ...
- TensorFlow的GPU设置
在使用GPU版的TensorFlow跑程序的时候,如果不特殊写代码注明,程序默认是占用所有主机上的GPU,但计算过程中只会用其中一块.也就是你看着所有GPU都被占用了,以为是在GPU并行计算,但实际上 ...
- Effective C++ 读后感笔记
1.赋值不一定是初始化.例如 AClassName::AClassName(const std::string &name, const std::string &address, c ...
- [RN] React Native 关闭所有黄色警告
[RN] React Native 关闭所有黄色警告 console.ignoredYellowBox = ['Warning: BackAndroid is deprecated. Please u ...
- 1、kafka概述
一.关于消息队列 消息队列是一种应用间的通信方式,消息就是是指在应用之间传送的数据,它也是进程通信的一种重要的方式. 1.消息队列的基本架构 producer:消息生产者. broker:消息处理中心 ...
- vue-cli使用笔记
安装nodejs 安装vue-clinpm install -g vue-cli 使用vue-cli初始化项目vue init webpack my-project 进到目录cd my-project ...
- 【叔小生】JavaScript进阶篇
如何插入JS JS基础语法 语法.函数.方法 提取字符串substring() substring() 方法用于提取字符串中介于两个指定下标之间的字符. <!DOCTYPE HTML> & ...
- Interesting Vertices
Interesting Vertices(前向星+思维+dfs回溯) 参考博客:https://blog.csdn.net/I_believe_CWJ/article/details/10247201 ...