Java数值计算的总结

最近在做一些Java基础的练习OJ,其中大量涉及各种类型的混合计算,转换,精度计算以及日期推导。刷题的同时看看前辈们的讨论,在细节上感觉有许多新的认识。在此总结一下,以资备用。


#整型
整型,可以粗略的理解为整数,它又分为四种基本类型,byte,short,int,long。其基本数据长度与数值范围如下表。

类型 长度 取值范围
byte 1字节 -128-127
short 2字节 2 15 2 15 1 -2^{-15}-2^{15}-1
int 4字节 2 31 2 31 1 -2^{-31}-2^{31}-1
long 8字节 2 63 2 63 1 -2^{-63}-2^{63}-1

强化一下记忆,回顾一下最基本的知识,1byte=8bit,每个bit就是一个0,1,所以去掉一位作为符号位,每种类型能够表示的范围就很好算了,当他们前面注明unsigned时,变为无符号数,其范围为 0 2 ( l e n × 8 1 ) 0-2^{(len\times8-1)}

#浮点类型
浮点型,主要分为两类,float和double,他们分别是4字节和8字节。两者的区别在于长度和精度。double比float长了一倍,所以空间、处理速度什么的都要相应翻倍。使用时应尽量选择适当的。然而,我现在一般都只用double,这样好像不太好,我反省。

使用浮点型的数据类型时,还有个比较令人头痛的问题——精度,小数点前面的整数部分是用除余法获得的,而小数点后面的部分是用乘基数取整法得到的。如 0.2先0.2×2,得0.4取整数部分0作为小数的十分位,再0.4×2,得0.8,取整数0作为小数的百分位,一直重复上述步骤,直到所需的精度。故他的精度是令人捉急的,所以我们尽量不要用浮点数进行判断操作,即用“==”,这样可能永远都进不去这个if了。如果非要的话,比如在Junit里面做断言测试,那么可以采用精度范围来判断,一般可以采用“<10e-6”这种方式。

刚刚讨论了浮点数的精度问题,日常代码中我们最常做的就是把一个类型赋值给另一个类型,有些安全有些则不然,这就涉及到了各种类型间转换精度保证的问题。下图抄自《Java核心技术第一卷》,其中实线为精度安全的转换,虚线为精度丢失的转换。
这里写图片描述

然而工程中,很多时候需要精度有保障的浮点数计算,为了满足这个需求,BigDecimal和BigInteger类型就应运而生了,他们的加减乘除计算可以完美的保证运算精度,两个类型的用法一样,一个是针对小数的一个是处理整数的,其中BigDecimal类型的具体使用方式如下。

		BigDecimal n1 = new BigDecimal("3.6"); 
    	double five=2;
    	BigDecimal n2 = new BigDecimal(five);  
    	BigDecimal reslut = null;  
    	      	
    	reslut =  n1.add(n2);       							//加法  
    	System.out.println("3.6+2=" + reslut.doubleValue());  
    	     	
    	reslut  = n1.subtract(n2);  							//减法  
    	System.out.println("3.6-2=" + reslut.doubleValue());  
    	    
    	reslut  = n1.multiply(n2);      						//乘法
    	System.out.println("3.6*2=" + reslut.doubleValue());  
    	  
    	reslut  = n1.divide(n2);      							//除法  
    	System.out.println("3.6/2=" +reslut.doubleValue());  
    	
    	BigDecimal n3 = new BigDecimal("-1.5");
    	reslut  = n3.abs();      								//绝对值  
    	System.out.println("|-1.5|=" + reslut.doubleValue());  
    	
    	n1 = new BigDecimal("3.6"); 
    	n2 = new BigDecimal("1.2"); 
    	reslut  = n1.divide(n2);      							//除法  
    	System.out.println("3.6/1.2=" + reslut.doubleValue());  
    	reslut  = n1.divide(n2).stripTrailingZeros();      		//识别小数点  
    	System.out.println("3.6/1.2=" + reslut);  

这里写图片描述
#时间
时间也是平时计算时用的较多的内容,某日十天前是周几?某年某月第一个周三是几号?这些计算我刚刚碰到时,略加思索便开始大展拳脚写闰年判断方法,月份、星期的枚举,忙的不亦乐乎,但往往写完后各种bug蹦出来,杀人的心都有了。后来,知道还有Date、Calendar等类可供使用。其中Date类多用于记录时间,而计算时间则交给日历Calendar类来完成,其具体用法如下。

		Calendar cal=Calendar.getInstance();

		cal.add(Calendar.DAY_OF_MONTH, 15);

		String strDate=cal.get(Calendar.YEAR)+"年"+(cal.get(Calendar.MONTH)+1)+"月"+cal.get(Calendar.DATE)+"日";

		System.out.println("15天后的日期为:"+strDate);
				
		cal=Calendar.getInstance();
		
		cal.add(Calendar.DAY_OF_YEAR, -15);

		strDate=cal.get(Calendar.YEAR)+"年"+(cal.get(Calendar.MONTH)+1)+"月"+cal.get(Calendar.DATE)+"日";

		System.out.println("15天前的日期为:"+strDate);

![这里写图片描述](https://imgconvert.csdnimg.cn/aHR0cDovL2ltZy5ibG9nLmNzZG4ubmV0LzIwMTcwNDI4MDAyNzQzNDU5?x-oss-process=image/format,png)

上述是简单的计算,还可以深入精确的毫秒计算。另外需要注意的一点是,Calendar类把月定位0-11,使用时需注意转换。
发布了20 篇原创文章 · 获赞 13 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/kiba_zwei/article/details/70833611