基本数据类型(8种)
- 整型:long(8字节)、int(4字节、默认)、shot(2字节)、byte(1字节8位二进制表示)---转换成二进制直接存储
- 浮点型:double(8字节、默认)、float(4字节)---科学计数法存储
- 逻辑型:bollean(1字节)---true、false
- 字符型:char(2字节)
数据类型转换:
byte--->short--->int--->long--->float--->double
char--->int
对数据进行操作时注意溢出和舍入误差问题。
byte b1=1;
byte b2=2;
byte b=b1+b2;//编译错误。byte、shot型的运算,先转换成int,故结果要强制转换
byte b=(byte)(b1+b2);//编译正确
byte b=(byte)(b1+b2+126);//结果错误。byte为8位二进制,结果超出范围,溢出
溢出:
2的32次方=4294967296(无符号),带符号再除以2,负数比正数多一个,-2147483648~+2147483647。
当最小值再减小1,就会变成最大值;最大值再增加1,则会变成最小值;这种现象称为溢出。
舍入误差:
现象:
double j=3.0;
double k=2.9;
System.out.println("j-k = "+(j-k)); //结果为0.10000000000000009---舍入误差类似于十进制的1/3表示
double j1=4.0;
double k1=2.9;
System.out.println("j1-k1 = "+(j1-k1)); //结果为1.1
double j2=6.0;
double k2=4.9;
System.out.println("j2-k2 = "+(j2-k2)); //结果为1.0999999999999996---舍入误差
原因:(摘自http://blog.csdn.net/aya19880214/article/details/45891581。在这里谢谢博主分享)
首先得从计算机本身去讨论这个问题。我们知道,计算机并不能识别除了二进制数据以外的任何数据。无论我们使用何种编程语言,在何种编译环境下工作,都要先 把源程序翻译成二进制的机器码后才能被计算机识别。
以上面提到的情况为例,我们源程序里的2.4是十进制的,计算机不能直接识别,要先编译成二进制。但问 题来了,0.1的二进制表示并非是精确的0.1,反而最为接近的二进制表示是0.10000000000000009。原因在于浮点数由两部分组成:指数和尾数,这点如果知道怎样进行浮点数的二进制与十进制转换,应该是不难理解的。如果在这个转换的过程中,浮点数参与了计算,那么转换的过程就会变得不可预 知,并且变得不可逆。我们有理由相信,就是在这个过程中,发生了精度的丢失。而至于为什么有些浮点计算会得到准确的结果,应该也是碰巧那个计算的二进制与 十进制之间能够准确转换。
而
当输出单个浮点型数据的时候,可以正确输出,如
double d = 0.1;
System.out.println(d);
输出的是0.1,而不是0.10000000000000009。也就是说,不进行浮点计算的时候,在十进制里浮点数能正确显示。这更印证了我以上的想法,即如果浮点数参与了计算,那么浮点数二进制与十进制间的转换过程就会变得不可预知,并且变得不可逆。
事实上,浮点数并不适合用于精确计算,而适合进行科学计算。这里有一个小知识:既然float和double型用来表示带有小数点的数,那为什么我们不称 它们为“小数”或者“实数”,要叫浮点数呢?因为这些数都以科学计数法的形式存储。当一个数如50.534,转换成科学计数法的形式为5.053e1,它 的小数点移动到了一个新的位置(即浮动了)。可见,浮点数本来就是用于科学计算的,用来进行精确计算实在太不合适了。
解决方法:
使用java.math.BigDecimal类---专门精确计算浮点数的类。缺点是运行速度慢,需要调用运算方法来计算。
BigDecimal.setScale()方法用于格式化小数点
setScale(1)表示保留一位小数,默认用四舍五入方式
setScale(1,BigDecimal.ROUND_DOWN)直接删除多余的小数位,如2.35会变成2.3
setScale(1,BigDecimal.ROUND_UP)进位处理,2.35变成2.4
setScale(1,BigDecimal.ROUND_HALF_UP)四舍五入,2.35变成2.4
setScale(1)表示保留一位小数,默认用四舍五入方式
setScale(1,BigDecimal.ROUND_DOWN)直接删除多余的小数位,如2.35会变成2.3
setScale(1,BigDecimal.ROUND_UP)进位处理,2.35变成2.4
setScale(1,BigDecimal.ROUND_HALF_UP)四舍五入,2.35变成2.4
setScaler(1,BigDecimal.ROUND_HALF_DOWN)四舍五入,2.35变成2.3,如果是5则向下舍
BigDecimal其中一个构造函数以双精度浮点数作为输入,另一个以整数和换算因子作为输入,还有一个以小数的String表示作为输入。
注意:要小心使用BigDecimal(double)构造函数,因为如果不了解它,会在计算过程中产生舍入误差。请使用基于整数或String的构造函数。
如果使用 BigDecimal(double) 构造函数不恰当,在传递给 JDBC setBigDecimal() 方法时,会造成似乎很奇怪的 JDBC 驱动程序中的异常。例如,考虑以下 JDBC 代码,该代码希望将数字0.01存储到小数字段:
PreparedStatement ps = connection.prepareStatement("INSERT INTO Foo SET name=?, value=?");
ps.setString(1, "penny");
ps.setBigDecimal(2, new BigDecimal(0.01));
ps.executeUpdate();
在执行这段似乎无害的代码时会抛出一些令人迷惑不解的异常(这取决于具体的 JDBC 驱动程序),因为0.01的双精度近似值会导致大的换算值,这可能会使 JDBC 驱动程序或数据库感到迷惑。JDBC驱动程序会产生异常,但可能不会说明代码实际上错在哪里,除非意识到二进制浮点数的局限性。相反,使用 BigDecimal("0.01")或BigDecimal(1,2)构造BigDecimal来避免这类问题,因为这两种方法都可以精确地表示小数。
float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用java.math.BigDecimal。使用BigDecimal并且一定要用String来够造。
字符定义:
char c1='男';
//char c5='男性'; //错误
char c2='m';
char c3='6';
char c4=' ';
char c6=65; //表面上为字符型,实质上是整型
System.out.println(c6); //输出为字符型
System.out.println((int)c6); //输出时将字符型强制转换成了整型
System.out.println('2'+'2');
System.out.println(2+'2');
System.out.println(2+2);
char c7='\'';
System.out.println(c7);
char c8='\n';
System.out.println(c8); //println一次换行,\n一次换行
System.out.println('2'+'2');
每个char型变量占16bit(位),即就是两个字节。
在Java中字符的编码不是ASCII码,而是采用的Unicode编码。Unicode编码字符是用16位无符号整数表示的。有2的16次方(0-65535)个可能值。
字符有三种定义方式:
- 直接使用一对单引号包含的单个字符:char c1 = 'E';
- 通过Unicode编码值(\u0000-\uFFFF)直接表示:char c2 = '\u004E'; //表示大写字母E
- 使用整数(0-65535)直接赋值:char c3 = 65; //大写字母A