(byte)129 = -127问题分析
2018-03-08 15:34
232 查看
今天看Integer类源代码的时候,看到他有这样一个方法byteValue(),实现如下: /**
* Returns the value of this {@code Integer} as a {@code byte}
* after a narrowing primitive conversion.
* @jls 5.1.3 Narrowing Primitive Conversions
*/
public byte byteValue() {
return (byte)value;
}于是我顺手调用了这个方法 public static void testXvalue(){
Integer inte = new Integer(22222);
byte b =inte.byteValue();
结果得到的值是:b = -50 ???? 额,怎么回事? 原来是溢出了。
byte:1个字节, 8个bit位, 值范围 -128 ~ 127 (-2^7 ~ 2^7-1)。
int : 4个字节, 32个bit位 取值范围 -2^31 ~ 2^31-1
所以, 在进行类型转换的时候,当值超过127 时, byte就承受不了,开始溢出。(这种情况多发生在大转小的时候)
00000000 00000000 00000000 00000000;
例如 int = 7; 00000000 00000000 00000000 00000111;
btye的完整二进制表示法:
00000000
例如:byte= 7; 00000111;
有人可能会有疑问,这两个不是一样吗???? 不不不, 不要忽略int的 后面的 那三个字节。因为:
byte : 10000111 , 就变成了负数。而
int : 00000000 00000000 00000000 10000111 ; 还是一个正数。
额, 最后一位是在左边哦,不要问我为什么。 规定。
例如: int : 10000000 00000000 00000000 10000111; 表示的就是一个负数。
byte :10000111 ; 也是个负数。
那么这个呢: 10001111 ???? 不好说, 不知道他是表示几个字节的数值, 如果是byte 就是负数, 是int,short, 就是正数。
这个口诀涉及3个二进制专有名词: 原码,反码, 补码。
原码: 某个数值的二进制表达式。
例如 1 : 00000000 00000000 00000000 00000001
反码: 二进制表达式,除了最后一个符号位外,其他的取反(1变0, 0变1)后的结果。
例如 上面取反:01111111 11111111 11111111 11111110
补码: 取反后的表达式(反码) +1 的结果。
例如 上面取反:01111111 11111111 11111111 11111110
+1
-------------------------------------------------------
结果: 01111111 11111111 11111111 11111111
那么,进过如上三步后的结果: 01111111 11111111 11111111 11111111, 是不是就是 -1 , 的二进制表达式呢?
错,错,错, 还差一步, 你的符号位没有换,上面说过了 1----表示负数, 0------表示正数。
最后结果 : 11111111 11111111 11111111 11111111
=============================================================
int a=22222 : 01010110 11001110 ;( 后面的0 我就不补了)
转换成byte : 11001110 ; 因为byte只有一个字节,所以 01010110 这段二进制码是不属于byte的。 也叫溢出了。
好了, 最后的到的 byte(a) : 11001110; 一看就是负数。 计算他的值。
补码 : -1
11001101
反码: 10110010
原码 : 00110010 结果 50的 负数 -50.
------------------------------------------------------------------------------------------------
感觉用 减1, 好像很容易混,我试了一下, 正三步走也是正确的结果
反码 补码+1 取正
11001110 --------> 10110001 ----------> 10110010 --------> 00110010 结果还是-50
另外: Integer 类提供了一个 获取二进制码的方法:System.out.println(Integer.toBinaryString(22222));
//结果 101011011001110
System.out.println((byte)22222);
//结果 -50如果有问题的可以用这个方法来检查你的结果是否正确。
* Returns the value of this {@code Integer} as a {@code byte}
* after a narrowing primitive conversion.
* @jls 5.1.3 Narrowing Primitive Conversions
*/
public byte byteValue() {
return (byte)value;
}于是我顺手调用了这个方法 public static void testXvalue(){
Integer inte = new Integer(22222);
byte b =inte.byteValue();
结果得到的值是:b = -50 ???? 额,怎么回事? 原来是溢出了。
byte:1个字节, 8个bit位, 值范围 -128 ~ 127 (-2^7 ~ 2^7-1)。
int : 4个字节, 32个bit位 取值范围 -2^31 ~ 2^31-1
所以, 在进行类型转换的时候,当值超过127 时, byte就承受不了,开始溢出。(这种情况多发生在大转小的时候)
下面用二进制码来说明过程:
首先几个基础知识点:
第一个知识点:基础数据类型的完整二进制表示法
int 的完整二进制表示法:00000000 00000000 00000000 00000000;
例如 int = 7; 00000000 00000000 00000000 00000111;
btye的完整二进制表示法:
00000000
例如:byte= 7; 00000111;
有人可能会有疑问,这两个不是一样吗???? 不不不, 不要忽略int的 后面的 那三个字节。因为:
byte : 10000111 , 就变成了负数。而
int : 00000000 00000000 00000000 10000111 ; 还是一个正数。
第二个知识点: 二进制中的符号位。
二进制表示数值时, 他的最后一位并不参与数值的存储, 而仅仅用来表示符号(+或 -)即 正 ,反。额, 最后一位是在左边哦,不要问我为什么。 规定。
例如: int : 10000000 00000000 00000000 10000111; 表示的就是一个负数。
byte :10000111 ; 也是个负数。
那么这个呢: 10001111 ???? 不好说, 不知道他是表示几个字节的数值, 如果是byte 就是负数, 是int,short, 就是正数。
第三个知识点: 正数,负数之间的转换关系。
一个口诀: 负数 = 正数取反+1这个口诀涉及3个二进制专有名词: 原码,反码, 补码。
原码: 某个数值的二进制表达式。
例如 1 : 00000000 00000000 00000000 00000001
反码: 二进制表达式,除了最后一个符号位外,其他的取反(1变0, 0变1)后的结果。
例如 上面取反:01111111 11111111 11111111 11111110
补码: 取反后的表达式(反码) +1 的结果。
例如 上面取反:01111111 11111111 11111111 11111110
+1
-------------------------------------------------------
结果: 01111111 11111111 11111111 11111111
那么,进过如上三步后的结果: 01111111 11111111 11111111 11111111, 是不是就是 -1 , 的二进制表达式呢?
错,错,错, 还差一步, 你的符号位没有换,上面说过了 1----表示负数, 0------表示正数。
最后结果 : 11111111 11111111 11111111 11111111
=============================================================
下面进入正题, byte的溢出问题:
上面所提出的问题, int a = 22222, byte(a), 会溢出问题。int a=22222 : 01010110 11001110 ;( 后面的0 我就不补了)
转换成byte : 11001110 ; 因为byte只有一个字节,所以 01010110 这段二进制码是不属于byte的。 也叫溢出了。
好了, 最后的到的 byte(a) : 11001110; 一看就是负数。 计算他的值。
负数的二进制转十进制计算方法: 上面三步走,反着走;
结果 : 11001110补码 : -1
11001101
反码: 10110010
原码 : 00110010 结果 50的 负数 -50.
------------------------------------------------------------------------------------------------
感觉用 减1, 好像很容易混,我试了一下, 正三步走也是正确的结果
反码 补码+1 取正
11001110 --------> 10110001 ----------> 10110010 --------> 00110010 结果还是-50
另外: Integer 类提供了一个 获取二进制码的方法:System.out.println(Integer.toBinaryString(22222));
//结果 101011011001110
System.out.println((byte)22222);
//结果 -50如果有问题的可以用这个方法来检查你的结果是否正确。
相关文章推荐
- Java中(Integer)127 == (Integer)127和(Integer)129 == (Integer)129表达式结果差异分析
- Java中(Integer)127 == (Integer)127和(Integer)129 == (Integer)129表达式结果差异分析
- IDEA查看源码时提示:Library source does not match the bytecode for class的问题分析
- 关于java中byte只能表示-128~127的问题的解释及处理
- IDEA查看源码时提示:Library source does not match the bytecode for class的问题分析
- 使用Integer.parseInt()需要注意的问题分析
- DNS-BIND安装调试及过程问题分析解决
- 【转】最大子段和问题分析和总结
- Java读取文件byte转化String问题
- 007关于静态方法的代码分析问题
- Ajax异步提交数据返回值的换行问题实例分析
- 算法分析--书的页码问题
- 利用construct2制作游戏过程中个别问题的分析与总结
- Problem B. Investing at the Market 问题B 市场投资 分析 解决办法
- 缓存中常见的4种问题分析以及解决方案
- 动态规划——矩阵链乘问题分析
- 线性回归、逻辑回归等问题对比分析总结
- 浏览器html页面乱码问题分析
- 软件体系结构经典问题——KWIC的分析和解决
- oracle 一次诊断和解决CPU利用率高的问题分析