- java中int,float,long,double取值范围
public class TestOutOfBound { public static void main(String[] args) { System.out.println(Integer.MAX_VALUE-(-Integer.MAX_VALUE)); //内存溢出 System.out.println(Integer.MAX_VALUE); //2的31次方-1,10个数位,正的20亿左右,用在钱上面不一定够 System.out.println(Integer.MIN_VALUE); //负的2的31次方 System.out.println(Long.MAX_VALUE); //2的64次方-1,19个数位,很大了,可放心用在钱上面 System.out.println(Long.MIN_VALUE); //负的2的64次方 System.out.println(Float.MAX_VALUE); //2的128次方-1,38个数位,比long多了一倍,这个主要用来做简单数学精确运算使用 System.out.println(Float.MIN_VALUE); //2的-149次方 System.out.println(Double.MAX_VALUE); //2的1024次方-1,308个数位,是float数位的10倍,主要用来做复杂运算和天文运算 System.out.println(Double.MIN_VALUE); //2的-1074次方 } }
- float与double精度丢失问题
举例:double result = 1.0 - 0.9
结果:0.09999999999999998
原因:
float和double类型主要是为了科学计算和工程计算而设计的。他们执行二进制浮点运算,这是为了在广泛的数字范围上提供较为精确的快速近似计算而精心设计的。然而,它们并没有提供完全精确的结果,所以我们不应该用于精确计算的场合。float和double类型尤其不适合用于货币运算
因为要让一个float或double精确的表示0.1或者10的任何其他负数次方值是不可能的(其实道理很简单,十进制系统中能不能准确表示出1/3呢?同样二进制系统也无法准确表示1/10)
浮点运算很少是精确的,只要是超过精度能表示的范围就会产生误差。往往产生误差不是因为数的大小,而是因为数的精度。因此,产生的结果接近但不等于想要的结果。尤其在使用 float 和 double 作精确运算的时候要特别小心。
解决方法一:
int resultInt = 10 - 9; double result = (double) resultInt / 100;//最终时候自己控制小数点
解决方法二:
使用BigDecmal,而且构造参数使用String类型
《Effective Java》书中指出,float和double只能用来做科学计算或者是工程计算,在商业计算等精确计算中,我们要用java.math.BigDecimal
。
而且不能直接用double,而非要用 String来构造BigDecimal不可!BigDecimal(String value)
public static double add(double v1,double v2) public static double sub(double v1,double v2) public static double mul(double v1,double v2) public static double div(double v1,double v2) public static double div(double v1,double v2,int scale) public static double round(double v,int scale)
为什么非要用 String来构造BigDecimal
如果不用BigDecimal做除法时如果出现除不尽(循环小数)的情况,会抛异常
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result. at java.math.BigDecimal.divide(BigDecimal.java:1693)
这是BigDecimal进行除法运算时的坑
参考:为什么浮点型运算会造成精度丢失?
首先我们要搞清楚下面两个问题
- 十进制整数如何转化为二进制数
//11表示成二进制数 11/2=5 余 1 5/2=2 余 1 2/2=1 余 0 1/2=0 余 1 0结束 11二进制表示为(从下往上):1011
- 十进制小数如何转化为二进制数
//整数转二进制,除以后的结果为0了就结束了,所有的整数除以2一定能够最终得到0。所以整数永远可以用二进制精确表示(不会无限循环下去)但小数就不一定了 //0.9表示成二进制数 //算法是乘以2直到没有了小数为止 0.9*2=1.8 取整数部分 1 0.8(1.8的小数部分)*2=1.6 取整数部分 1 0.6*2=1.2 取整数部分 1 0.2*2=0.4 取整数部分 0 0.4*2=0.8 取整数部分 0 0.8*2=1.6 取整数部分 1 0.6*2=1.2 取整数部分 0 ......... 0.9二进制表示为(从上往下): 1100100100100...... //注意:上面的计算过程循环了,也就是说*2永远不可能消灭小数部分,这样算法将无限下去。很显然,小数的二进制表示有时是不可能精确的 。其实道理很简单,十进制系统中能不能准确表示出1/3呢?同样二进制系统也无法准确表示1/10。这也就解释了为什么浮点型减法出现了"减不尽"的精度丢失问题。