java 基本数据类型

java 基本数据类型共有8个。

数据类型大小范围默认值
byte(字节)8-128 ~ 1270
short(短整型)16-32768 ~ 327680
int32-2147483648 ~ 214748364800
long64-9233372036854477808 ~ 92333720368544778080
float(单精度浮点型)32-3.4E38 ~ 3.4E380.0f
double(双精度浮点型)64-1.79E308 ~ +1.79E3080.0d

Java是一种可以撰写跨平台应用程序的面向对象的程序设计语言,程序不是直接运行在本地操作系统上,而是运行在JVM上,java虚拟机与系统无关,因此不管是32bit还是64bit操作系统,java的基本类型长度固定。

浮点型内存结构

浮点数在内存中是科学计数法 来存储的,一个浮点数由三部分组成:符号位S、底数M和指数E。
这里写图片描述

float

1bit(符号位)8bit(指数位)23bit(尾数位)

  • 符号位:表示浮点数的正负。0正;1负
  • 指数:占用8bit位二进制数,以移码存储,取值范围0~255。因为指数可正可负,存储的数据为元数据+127
  • 底数:实际是占用24bit的一个值(1.000 0000 0000 0000 0000 0000),由于最高位始终为1,因此”1.”省略不存储,只存储小数点后面的23bit

举例:
17.625在内存中的存储形式
将十进制的小数转换为二进制的小数的方法:小数*2,取整数部分

  • 17转二进制 10001
  • 0.625转二进制
    0.625 * 2 = 1.25 ————1 (第一位)
    0.25 * 2 = 0.5 ————0 (第二位)
    0.5 * 2 = 1.0 ————1 (第三位)
    因此0.625转二进制为101

17.625的二进制表示:10001.101
小数点向左移动四位,由1.0001101知:底数为0001101,指数为4,必须加127进行修正,因此指数为10000011,
综上:17.625的 float 存储格式就是: 0 10000011 00011010000000000000000

double

1bit(符号位)11bit(指数位)52bit(尾数位)

指数范围:-1024 ~ 1023
double的取值范围:-2^1024 ~ 2^1023,也即:-1.79E308 ~ +1.79E308

精度

float和double的精度由 尾数的位数 来决定。
float的底数有23位,2^23=8388608,一共七位,因此单精度浮点数最多能有七位有效数字(根据指数位移动小数点只能补0,并非有效数字),但绝对能保证的为6位,因此float的精度为6~7位有效数字。
double:2^52 = 4503599627370496,一共16位,同理,double的精度为15~16位

浮点数的误差

十进制浮点数转二进制可能存在误差

2.2f转二进制

  • 0.2*2=0.4
  • 0.4*2=0.8
  • 0.8*2=1.6
  • 0.6*2=1.2
  • 0.2*2=0.4

这样永远也不可能乘到=1.0,得到的二进制是一个无限循环的排列 0011 0011 0011 0011 0011 …取前23位作为float的尾数。以该二进制得到的十进制也不再是2.2,而是2.200000047683716。因此浮点数表示会产生些许误差,double类型同理。

单精度转双精度可能存在误差

原理同上。以上两种情况,若浮点数能用二进制表示,如2.25,则不会存在误差。

移码

移码是对于某一个系列或集合的数使它们都映射到正数轴上去,即在数轴上把数都统一往右移动n位,使得所有的数都不为负数。补码的符号位取反即为移码,一般用做浮点数的阶码。

8bit补码、移码范围

  • 8位补码的取值范围是-128~127,为什么不是-127~127?
  • 官方定义,nbit补码的取值范围:[-2E(n-1),2E(n-1)-1],补码的零没有正负之分。为什么?
  • 8bit移码范围:0~255

8bit补码、移码能表示的所有情况:

8bit补码十进制8bit移码十进制无符号数
0 000 000001 000 0000128
0 000 000111 000 0001129
0 111 11111271 111 1111255
1 000 0000-1280 000 00000
1 000 0001-1270 000 00011
1 000 0010-1260 000 00102
1 111 1110-20 111 1110126
1 111 1111-10 111 1111127

问题主要在于,计算机中1 000 0000表示的数值是多少?

转换一下思想,计算机中对于负数的存储:先取绝对值,然后取反加一
-128绝对值128,转换为二进制为1000 0000,取反为0111 1111 ,加一为1000 0000

因此:计算机中补码1000 0000表示的是-128,而不是-0
因此:8bit补码的取值范围-128~127
因此:官方定义,补码的0没有正负区分

为什么不用补码存储浮点数的阶码

  • 由于移码都不为负数,所以直接可以由移码的表示形式看出对应数值的大小(这里是把移码当做无符号数来比较大小的,而不必考虑符号,比用补码好多了,补码是要变换成原码再比较的)
  • 阶码用移码表示的话,简化了对于“0”的判断,即当移码的各位都为0的话,那么该移码对应的数据是能够表示的数据中的最小值(移码是把数据集合映射到正数轴上,所以0是数据集合中最小值的映射)。
  • 用移码来表示阶码的话可以提高表示数据的精度。如果不是采用移码来表示阶码的话,那么当阶码就会出现负值,这样的话当需要把该数据转换成非阶码浮点数据时我们将就需要对尾数进行左移(做乘法运算),这样的话我们会发现最先移去的是尾数的高位,因此这种方法不利于数据的精度表示。而对于才用移码表示阶码的话,我们在转换时是做右移操作,这样最先移去的是最低位,这样比较好地保持了数据的精度。

机器零

  • 浮点数尾数为0时,不论其阶码为何值,按机器零处理
  • 浮点数阶码小于等于浮点机所能表示的最小阶码时,不论其尾数为何值,按机器零处理。

8bit阶码用补码表示的最小阶码为-128,二进制为1 000 0000
8bit阶码用移码表示的最小阶码为0,二进制为 0000 0000
可以看出移码表示阶码有利于机器中“判0”电路的实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值