Java问题总结1
一、关于原码、反码、补码问题。
1.原码
将一个整数转换成二进制形式,就是其原码。例如short a = 6; a 的原码就是0000 0000 0000 0110;更改 a 的值a = -18; 此时 a 的原码就是1000 0000 0001 0010。
通俗的理解,原码就是一个整数本来的二进制形式。
2.反码
对于正数,它的反码就是其原码(原码和反码相同);负数的反码是将原码中除符号位以外的所有位(数值位)取反,也就是 0 变成 1,1 变成 0。例如short a = 6; a 的原码和反码都是0000 0000 0000 0110;更改 a 的值a = -18; 此时 a 的反码是1111 1111 1110 1101。
3.补码
对于正数,它的补码就是其原码(原码、反码、补码都相同);负数的补码是其反码加 1。例如short a = 6; a 的原码、反码、补码都是0000 0000 0000 0110;更改 a 的值a = -18; 此时 a 的补码是1111 1111 1110 1110。
可以认为,补码是在反码的基础上打了一个补丁,进行了一下修正,所以叫“补码”。
原码、反码、补码的概念只对负数有实际意义,对于正数,原码、反码、补码都是一样的。
二、其他遇到问题。
1.枚举基本用法
仔细阅读示例: EnumTest.java,运行它,分析运行结果?代码如下
1 public static void main(String[] args) { 2 Size s=Size.SMALL; 3 Size t=Size.LARGE; 4 //s和t引用同一个对象? 5 System.out.println(s==t); // 6 //是原始数据类型吗? 7 System.out.println(s.getClass().isPrimitive()); 8 //从字符串中转换 9 Size u=Size.valueOf("SMALL"); 10 System.out.println(s==u); //true 11 //列出它的所有值ֵ 12 for(Size value:Size.values()){ 13 System.out.println(value); 14 } 15 } 16 enum Size{SMALL,MEDIUM,LARGE};
运行结果 分析
false s和t引用的并非同一个对象,s引用的是SMALL,t引用的是LARGE。
false 枚举类型并非原始数据类型(原始类型一共有8种,它们分别是char,boolean,byte,short,int,long,float,double)
true 调用valueOf(“SMALL”)将返回 Size.SMALL,将字符串转换为枚举。
SMALL 利用values()遍历输出枚举。
MEDIUM
LARGE
2.println()的输出问题
1 int X=100; 2 int Y=200; 3 System.out.println("X+Y="+X+Y); 4 System.out.println(X+Y+"=X+Y");
输出结果为
1 X+Y=100200 2 300=X+Y
两个+的意义不同,第一个+是连接运算符,第二个是加法运算符。
若加括号改变运算优先级,改为
System.out.println("X+Y="+(X+Y));
则输出
X+Y=300
3.double类型计算结果不精确问题
1 System.out.println("0.05 + 0.01 = " + (0.05 + 0.01)); 2 System.out.println("1.0 - 0.42 = " + (1.0 - 0.42)); 3 System.out.println("4.015 * 100 = " + (4.015 * 100)); 4 System.out.println("123.3 / 100 = " + (123.3 / 100));
结果为
1 0.05 + 0.01 = 0.060000000000000005 2 1.0 - 0.42 = 0.5800000000000001 3 4.015 * 100 = 401.49999999999994 4 123.3 / 100 = 1.2329999999999999
会清楚的发现每个关于double的计算都有一点点误差。
原因涉及到二进制与十进制的转换问题。
N进制可以理解为:数值×基数的幂,例如我们熟悉的十进制数123.4=1×10²+2×10+3×(10的0次幂)+4×(10的-1次幂);
其它进制的也是同理,例如二进制数11.01=1×2+1×(2的0次幂)+0+1×(2的-2次幂)=十进制的3.25。
double类型的数值占用64bit,即64个二进制数,除去最高位表示正负符号的位,在最低位上一定会与实际数据存在误差(除非实际数据恰好是2的n次方)。
解决方案:
使用BigDecimal类 Demo:TestBigDecimal.java
import java.math.BigDecimal;
在构建BigDecimal对象时应使用字符串而不是double数值,否则,仍有可能引发计算精度问题。
1 BigDecimal f1 = new BigDecimal("0.05"); 2 BigDecimal f2 = BigDecimal.valueOf(0.01); 3 BigDecimal f3 = new BigDecimal(0.05); 4 System.out.println("下面使用String作为BigDecimal构造器参数的计算结果:"); 5 System.out.println("0.05 + 0.01 = " + f1.add(f2)); 6 System.out.println("0.05 - 0.01 = " + f1.subtract(f2)); 7 System.out.println("0.05 * 0.01 = " + f1.multiply(f2)); 8 System.out.println("0.05 / 0.01 = " + f1.divide(f2)); 9 System.out.println("下面使用double作为BigDecimal构造器参数的计算结果:"); 10 System.out.println("0.05 + 0.01 = " + f3.add(f2)); 11 System.out.println("0.05 - 0.01 = " + f3.subtract(f2)); 12 System.out.println("0.05 * 0.01 = " + f3.multiply(f2)); 13 System.out.println("0.05 / 0.01 = " + f3.divide(f2));
运行结果
1 下面使用String作为BigDecimal构造器参数的计算结果: 2 0.05 + 0.01 = 0.06 3 0.05 - 0.01 = 0.04 4 0.05 * 0.01 = 0.0005 5 0.05 / 0.01 = 5 6 下面使用double作为BigDecimal构造器参数的计算结果: 7 0.05 + 0.01 = 0.06000000000000000277555756156289135105907917022705078125 8 0.05 - 0.01 = 0.04000000000000000277555756156289135105907917022705078125 9 0.05 * 0.01 = 0.0005000000000000000277555756156289135105907917022705078125 10 0.05 / 0.01 = 5.000000000000000277555756156289135105907917022705078125
浙公网安备 33010602011771号