在java的Math類中,提供了許許多多的和數學計算有關的方法,其中也包括取整的,關於取整的有向下取整的floor(double d)返回值double,rint(double d),round(double d)和round(float f)。
但是,其中和四捨五入相近的方法只有rint和round方法,如果單獨使用這兩個方法的話,所得到的結果和我們預期的結果不一樣,
比如round(-1.5)所得到的結果是-1,而不是我們預期的-2;
而rint(-1.5)得到的結果是-2.0,但是rint(2.5)得到的結果卻是2.0,和我們預期的3.0也不一樣
我們分析一下爲什麼會這樣子,首先看一下round方法的API:
Returns the result of rounding the argument to an integer. The result is equivalent to (long) Math.floor(d+0.5)
.
Special cases:
round(+0.0) = +0.0
round(-0.0) = +0.0
round((anything > Long.MAX_VALUE) = Long.MAX_VALUE
round((anything < Long.MIN_VALUE) = Long.MIN_VALUE
round(+infinity) = Long.MAX_VALUE
round(-infinity) = Long.MIN_VALUE
round(NaN) = +0.0
Parameters
d | the value to be rounded. |
---|
Returns
- the closest integer to the argument.
即返回一個和參數相近的整型,其結果相當於(long) Math.floor(d+0.5)
的值,對於Math.floor(double d)方法,其結果是d向下取整,所以對於round(-1.5)來說,它的返回值是要加上0.5再向下取整,也就是-1.5+0.5=-1.0,1.0向下取整還是1.0,所以返回的是長整型1,但是計算正數的時候就沒有這個問題。比如說round(1.5),計算的就是(long)(1.5+0.5)=(long)2.0=2L,所以對於round方法來說對於負數四捨五入所得到的結果是不正確的。
然後我們來看一下rint方法的API,這個方法與四捨五入差的有點遠。
public static double rint (double d)
Returns the double conversion of the result of rounding the argument to an integer. Tie breaks are rounded towards even.
Special cases:
rint(+0.0) = +0.0
rint(-0.0) = -0.0
rint(+infinity) = +infinity
rint(-infinity) = -infinity
rint(NaN) = NaN
Parameters
d | the value to be rounded. |
---|
Returns
- the closest integer to the argument (as a double).
這個方法也是返回一個和參數相近的整型,當有兩個整數的時候,會返回偶數的那個。
也就是說,當遇到幾點五的時候,纔會遇到兩個整數,所以對於rint(-1.5)來說,會有-1.0和-2.0兩個整數與-1.5相近,但是他會取偶數-2.0,。對於rint(-1.3)只有一個整數-1.0與-1.3接近,所以此時不會有誤差。但是對於rint(2.5),有2.0和3.0與2.5接近,他會返回與我們預期不一樣的偶數2.0,rint(-2.5)會返回-2.0,所以對於rint方法,當遇到偶數點五的時候,結果會不一樣。
綜合上述,如果想用round方法就得解決負數問題,所以可以用絕對值Math.abs方法來解決。下面爲代碼:
方法一:
public double run(double num){ double a=Math.signum(num); //判斷是正數負數還是0,負數返回-1.0,正數返回1.0 if(a<0.0) return 0.0-Math.round(Math.abs(num)); return Math.round(num); }
如果想用rint方法就得解決偶數點五的問題,下面爲代碼:
方法二:
public double run(double num){ if(Math.floor(Math.abs(num))%2!=0) return Math.rint(num); if(five(num)) if(Math.signum(num)<0.0) return Math.rint(num)-1.0; else if(Math.signum(num)>0.0) return Math.rint(num)+1.0; return Math.rint(num); } public boolean five(double n){ String[] split = String.valueOf(n).split("\\."); if(split[1].startsWith("5")) return true; else return false; }
當然也有其他方法,比如用保留小數的方法string的格式化方法都行
因爲方法二效率低,所以建議使用方法一。
本人第一次寫博客,還是學生,所以有不足之處請指正,請諒解不足或錯誤之處,謝謝!