目录
- Java是一种强类型的语言
- 而且我们的Java有一种能够表示任意精度的算数包,通常称为大数,但是他是对象
整型变量 int
基本语法格式
int a=10;//初始化时并赋值
int a;
内存大小
int 大小为4个字节(byte),与操作系统的和JVM的版本无关,像C语言可能就会受到编译器的影响,是为了实现跨平台
整型的范围
- 也就是-231至231-1
- 因为4字节表示有32位,一位用来表示正负
数据溢出问题
为什么会溢出
因为2^32-1的数据的大小不够用,还不够表述出马云的个人资产,所以引出了long类型
长整型 long
long a=10L;
long a=10l;
long a=1000_000_000;//可以为数字字面量加下划线,这些下划线只是让人更易读,Java编译器会自动去除这些下划线
为什么要加L呢?
字面量 ——程序中直接写出来的值
整型的字面量,默认是整型(int),浮点数的字面量,默认是double,所以要加一个L(l)表示它是long类型,否则会发生隐式转换
内存的大小
long类型的大小是8字节
long的数据范围
-263至263-1
短整型 short
short a=20;
内存大小
2个字节 数值范围是 -215至-215-1
基本没啥用
比特型 byte
byte a=1;
内存大小
一个字节 ,数值访问 -128到127
主要用于文件和网络的传输
浮点数 float和double
float f=1.2f;
float f=1.2F;
double d=1.2;
在JAVA中直接写出来的字母常量的浮点数都是double类型的,所以在flaot需要特别的声明一下
内存大小
float的大小为4个字节,double的字节是8个字节 在内存中采用指数的形式来模拟
浮点数存储规则
根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:
(-1)^S * M * 2^E
- (-1)^S S表示符号位,当s=0,V为正数;当s=1,V为负数。
- M表示有效数字,大于等于1,小于2。
- 2^E E表示指数位。
举例来说:
十进制的5.0,写成二进制是 101.0 ,相当于 1.01×2^2 。
那么,按照上面V的格式,可以得出s=0,M=1.01,E=2。
十进制的-5.0,写成二进制是 -101.0 ,相当于 -1.01×2^2 。那么,s=1,M=1.01,E=2。
IEEE 754规定:
- 对于32位的浮点数,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。
- 对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。
IEEE 754对有效数字M和指数E,还有一些特别规定。
- 前面说过, 1≤M<2 ,也就是说,M必须写成 1.xxxxxx 的形式,其中xxxxxx表示小数部分。
- IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的 xxxxxx部分。比如保存1.01的时 候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。以32位 浮点数为例,留给M只有23位, 将第一位的1舍去以后,等于可以保存24位有效数字。
至于指数E,情况就比较复杂。
- 首先,E为一个无符号整数(unsigned int)
- 这意味着,如果E为8位,它的取值范围为0255;如果E为11位,它的取值范围为02047。但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数 是127;对于11位的E,这个中间 数是1023。比如,2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即 10001001。
然后,指数E从内存中取出还可以再分成三种情况:
E不全为0或不全为1
这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将 有效数字M前加上第一位的1。
比如:0.5(1/2)的二进制形式为0.1,由于规定正数部分必须为1,即将小数点右移1位,则为1.0*2^(-1),其阶码为-1+127=126,表示为 01111110,而尾数1.0去掉整数部分为0,补齐0到23位00000000000000000000000,则其二进 制表示形式为:
E全为0
这时,浮点数的指数E等于1-127(或者1-1023)即为真实值, 有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。
E全为1
这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);
关于3*0.1==0.3
-
答案是不相同的
-
在上面,我们知道我们的浮点数在计算机以指数形式存储,其原理还是得用我们的二进制来表示
- 比如0.75 可以用 2-1+2-2来表示 0.11 1.1*2^-1 在计算机中变成 S=0 E=-1+127 M=1
- 但是这个0.1我们是不能用二进制位精确表达出来的,所以肯定会存在误差
如何解决
- 仍使用double类型,但是只看小数前6位,后面的忽略不计
- 使用BigDecimal来代替double使用
如果的基本整数和浮点数的精度不能满足需求,可以使用java.math包下两个很有用的类
BigInteger 实现任意精度的整数运算
- BigInteger a=new BigInteger(“123”); //第一种,参数是字符串
- BigInteger a=BigInteger.valueOf(123); //第二种,参数可以是int、long
BigDecimal 实现任意精度的浮点数运算
BigDecimal 常用的构造方法如下。
BigDecimal(double val):实例化时将双精度型转换为 BigDecimal 类型。
BigDecimal(String val):实例化时将字符串形式转换为 BigDecimal 类型。
BigDecimal add(BigDecimal augend) // 加法操作 BigDecimal subtract(BigDecimal subtrahend) // 减法操作 BigDecimal multiply(BigDecimal multiplieand) // 乘法操作 BigDecimal divide(BigDecimal divisor,int scale,int roundingMode ) // 除法操作
字符型 char
char a='a';
char b='A';
char c='哈';
内存大小
-
占两个字节,在C中是一个字节,而且它可以存储中文
-
这是C做不到的C言中使用 ASCII 表示字符, 而 Java 中使用 Unicode 表示字符. 因此一 个字符占用两个字节, 表示的字符种类更多, 包括中文
-
在Java中,char类型表示的是UTF-16的一个代码单元,而不是Uncoide的字符 字符集和char的关系
布尔类型 boolean
boolean b=true;
boolean b=false;
注意点
-
boolean只有两个值,真就是true,假就是false
-
Java 的 boolean 类型和 int 不能相互转换 , 不存在 1 表示 true, 0 表示 false 这样的用法
-
如何将boolean变成0或者1
-
boolean类型在我们的官方文档写的是 It's virtual machine dependent. // 由虚拟机自己实现
- 我们都知道,Java语言中有个boolean类型。每个boolean类型的变量中存储的是一个true或者是false的逻辑值。那么存储这个逻辑值,需要多大的空间呢?从理论上来讲,存储这个逻辑值只需要1个位(bit)就可以了,所以很多教科书上谈到这个问题的时候,也说boolean类型的数据在内存中只占1个位。
- 但是稍微有点计算机常识的人都知道:计算机完成寻址操作的时候,是以字节为最小单位进行的。也就是说每次要读取内存中数据的时候,最小只能精确到1个字节,不能单独读取某个位上的信息。如果boolean类型的变量的值只占1个位,计算机每次读取到1个字节的信息,里面会包含8个boolean变量的值。计算机就不得不通过某种算法去确定这8个值中,哪一个才是我们要找的值。这样做显然非常不合理,因为要完成这个“8选1”的操作又会增加运算工作量。那么Java虚拟机到底是怎样存储boolean值呢?
- 在《虚拟机规范》中,对boolean类型的存储有专门的解释,文中说到:“虽然定义了boolean这种数据类型,但是只对它提供了非常有限的支持。在Java虚拟机中没有任何供boolean值专用的字节码指令,Java语言表达式所操作的boolean值,在编译之后都使用Java虚拟机中的int数据类型来代替,而boolean数组将会被编码成Java虚拟机的byte数组,(因此)每个boolean元素占8位”。
- 变成int类型,是因为我们很多的CPU都是32位,这样的存取效率是最高的