一、 整数在Java虚拟机中的标识
java虚拟机中的整数:byte、short、int、long四种;分别标识8位、16位、32位、64位有符号整数。
整数在计算机中使用补码来表示,java虚拟机中也同理。
原码:符号位加上数字的二进制表示
int 10 的原码为:00000000 00000000 00000000 00001010
int -10 的原码为: 10000000 00000000 00000000 00001010
反码:就是在原码的基础上符号位不变其余取反
int -10的反码为: 11111111 11111111 11111111 11110101
补码:负数的补码就是反码加1,正整数的补码就是原码本身
int 10 的补码:00000000 00000000 00000000 00001010
int -10的补码:11111111 11111111 11111111 11110110
int a = -10;
for (int i=0;i<32;i++){
int t=(a & 0x80000000 >>>)>>>>(31-i);
System.out.print(t);
}
以上代码可以打印-10在虚拟机内的时间表示:
11111111111111111111111111110110
使用补码作为计算机内的时间存储的好处
- 可以统一数字0的表示
由于0即非正数,也非负数
如果0为正数:00000000 00000000 00000000 00000000
如果0位负数:
原码表示:10000000 00000000 00000000 00000000
反码表示:11111111 11111111 11111111 11111111
补码在反码的基础上加1,表示如下:
补码表示:00000000 00000000 00000000 0000000
可以看到使用补码作为整数编码,可以解决数字0的存储问题
- 使用补码可以简化整数的加减法计算
使用补码可以简化整数的加减法计算,将减法计算视为加法计算,实现减法和加法的完全统一,实现正数和服务加法的统一
如果 byte -6+5的过程如下:
-6 的补码:11111010
5 的补码:00000101
直接相加得: 11111111 (-1)
计算byte 4+6的运算过程如下:
4的补码:00000100
6的补码:00000110
计算可得:00001010 (10)
使用补码表示只需要将补码简单地相加,无需区别正数或者负数;
二、浮点数在java虚拟机中的表示
浮点数:float 32位和 double64位 两种
java虚拟机对于浮点存储参考了IEEE745的规范
以float为例:在IEEEE745规范中浮点数的组成分为三部分:符号位(1位)、字数位(8位)、尾数位(23位)
s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm
sflag表示符号,s为0时,sflag=1 ;s为1时,sflag=-1;m为尾数值,实际占用空间为23位,但是根据e的取值,有24位精度;当e全为0时,尾数位附近为0,否则尾数位附加为1;e为指数位,用8个字节;
float -5 : 1 10000001 01000000000000000000000
符号位为1标识负数,指数位为10000001,表示129.
尾数位为:01000000000000000000000 。因为e不为0,故实际的尾数位为101000000000000000000000
尾数位表示2的指数次幂的和每一位表示和数列中的对应项是否为0;
故 1 10000001 01000000000000000000000 的值为:
float的特殊数字
描述 | 表示方式 |
---|---|
正无穷 | 0 11111111 00000000000000000000000 |
负无穷 | 1 11111111 00000000000000000000000 |
NaN | 0 11111111 10000000000000000000000 |
最大浮点数(3.4028235E38) | 0 11111110 11111111111111111111111 |
最小规范化正浮点数(1.17549435E-38) | 0 00000001 00000000000000000000000 |
最小正浮点数(1.4E-45) | 0 00000000 00000000000000000000001 |
零 | 0 00000000 00000000000000000000000 |
注:指数为全为1标识无穷大和NaN的特殊数字;指数位全为0为非规范化的浮点数。
在Java中使用Float.floatToRawIntBits()函数可以获取一个单精度浮点数的IEEE 754 表示。
float a = -5;
System.out.println(Integer.toBinaryString(Float.floatToRawIntBits(a)));
程序运行输出:
11000000101000000000000000000000
其中,Float.floatToRawIntBits()函数最终由native方法实现:如下
JNIEXPORT jint JNICALL
Java_java_lang_Float_floatToRawIntBits(JNIEnv *env, jclass unused, jfloat v)
{
union {
int i;
float f;
} u;
u.f = (float)v;
return (jint)u.i;
}
为了获取float的内部表示,使用了C语音中union自然实现这个转换。
学习笔记。。。
来源:CSDN
作者:coding一百年
链接:https://blog.csdn.net/hdAccpli/article/details/104494238