【Java】深入探讨Java数值舍入问题
常見的舍入方式
四舍五入
我們?cè)趯W(xué)習(xí)計(jì)算機(jī)科學(xué)之前,以及日常生活中,用的是四舍五入。
所謂四舍五入,就是取4即歸0,取5即歸1,這個(gè)問題與我們需要的精度有關(guān)。
在計(jì)算機(jī)科學(xué)中一般用round() 表示四舍五入。
比如0.499999,這是一個(gè)六位小數(shù),我們想要四舍五入,就要看精度。
精確到1,結(jié)果是0
精確到0.1.結(jié)果是0.5
精確到0.01,結(jié)果是0.50
……
向上取整
向上取整是一種無視四舍五入的行為,在計(jì)算機(jī)科學(xué)中應(yīng)用廣泛,意為取大于等于該數(shù)值的最小整數(shù)。
符號(hào)??,英文Ceiling,通常寫作ceil()。
英語中,ceil 的一個(gè)意思是 “天花板”,這樣我們就不難理解了。
ceil()一般應(yīng)用于浮點(diǎn)數(shù),如果不是浮點(diǎn)的話,本就是整數(shù),有什么取整的必要呢?
比如0.499999,上整就是1
比如-0.499999,上整就是0
向下取整
向下取整是一種無視四舍五入的行為,在計(jì)算機(jī)科學(xué)中應(yīng)用廣泛,意為取小于等于該數(shù)值的最大整數(shù)。
符號(hào)??,英文Floor,通常寫作floor()。
英語中,floor 的一個(gè)意思是 “地板”,這樣我們就不難理解了。
不難發(fā)現(xiàn),上整和下整是恰好相反的,所以也是應(yīng)用于浮點(diǎn)的。
比如0.499999,下整就是0
比如-0.499999,下整就是-1
不難發(fā)現(xiàn),?x? - ?x? = 1
截?cái)嗳≌?/h2>
截?cái)嗳≌且环N無視四舍五入的行為,在計(jì)算機(jī)科學(xué)中應(yīng)用廣泛,意為取舍去小數(shù)點(diǎn)和小數(shù)點(diǎn)后所有數(shù)位的整數(shù)。
比如0.499999,截?cái)嗳≌褪?
比如-0.499999,截?cái)嗳≌彩?
向兩端取整
向兩端取整是一種無視四舍五入的行為,在計(jì)算機(jī)科學(xué)中應(yīng)用廣泛,意為取臨近的∞方向的整數(shù)。
比如0.5,向兩端取整就是1
比如-0.5,向兩端取整就是-1
Math類中的舍入問題
主要有以下幾種舍入方式:
- ceil?(double a):作用是返回大于或等于參數(shù)且數(shù)值上等于整數(shù)的最小(最接近負(fù)無窮大)的浮點(diǎn)數(shù)
返回double型
解釋的通俗點(diǎn)就是向上取整后轉(zhuǎn)成數(shù)學(xué)上相等的double型 - floor?(double a):作用是返回小于或等于參數(shù)且數(shù)值上等于整數(shù)的最大(最接近正無窮大)的浮點(diǎn)數(shù)
返回double型 - nextDown?(…d/f):作用是返回在負(fù)無窮大方向上與d/f相鄰的浮點(diǎn)值
參數(shù)可以是double d、float f兩種,返回對(duì)應(yīng)的類型 - nextUp?(…d/f):作用是返回在正無窮大方向上與d/f相鄰的浮點(diǎn)值
參數(shù)可以是double d、float f兩種,返回對(duì)應(yīng)的類型 - rint?(double a):作用是返回在數(shù)學(xué)上等于與參數(shù)值最接近且是整數(shù)的double
返回double型
解釋的通俗一點(diǎn)就是四舍五入后取數(shù)學(xué)上相等的double型浮點(diǎn) - round?(…a):作用是返回參數(shù)四舍五入后的整數(shù)值
參數(shù)可以是double、float兩種
double參數(shù)返回long,float參數(shù)返回int
nextDown()?、nextUp()?、rint?()? 按照各自的規(guī)則舍入得浮點(diǎn)。
ceil?()?、floor()??、round()?分別是前面提的,取整得整數(shù),很常見。
除法的舍入問題
System.out.println(1/2);結(jié)果是什么?
System.out.println(-1/2);結(jié)果又是什么?
答案都是一樣的:
0
為什么呢?
整數(shù)除整數(shù),除號(hào)直接截?cái)嗳≌?#xff0c;正負(fù)號(hào)規(guī)則相同,相當(dāng)于直接砍去小數(shù)點(diǎn)和小數(shù)點(diǎn)后數(shù)位。
Java不像Python還分/和//,只有/,那怎么能精確呢?
當(dāng)然是轉(zhuǎn)型為浮點(diǎn)啦:
答案:
0.5
那浮點(diǎn)精確嗎?
System.out.println(0.1+0.2);結(jié)果是什么?
答案:
0.30000000000000004
為什么呢?
簡(jiǎn)而言之,double雙精度浮點(diǎn)數(shù),遵循IEEE754,64位,52位小數(shù)+11位指數(shù)+1位符號(hào)。
計(jì)算機(jī)沒有分?jǐn)?shù),也沒有十進(jìn)制小數(shù),所以只能用二進(jìn)制小數(shù)表示,難免不精確。
用更精確的BigDecimal算一下:
0.3000000000000000166533453693773481063544750213623046875
只能說相對(duì)精確了很多,也不能說完全精確了,畢竟是計(jì)算機(jī)。
printf()的舍入問題
System.out.printf("%.0f", 0.5);結(jié)果是什么?
System.out.printf("%.0f", -0.5);結(jié)果又是什么?
答案分別是:
1
-1
可見printf()的浮點(diǎn)舍入方式是向兩端取整。
double向float強(qiáng)轉(zhuǎn)的舍入問題
我們都知道,double表示64位雙精度浮點(diǎn)數(shù),float代表32位單精度浮點(diǎn)數(shù),double精確度高,也是默認(rèn)的浮點(diǎn)數(shù)類型。
看下面的代碼:
double a = 0.555555555; float b = (float)a;b的值是多少?
答案是:
0.5555556
而下面的情況呢?
double a = 0.55555554; float b = (float)a;b的值是:
0.5555555
可見printf()的浮點(diǎn)舍入方式是四舍五入。
BigDecimal處理舍入問題的八種方式
原先BigDecimal類舍入采取本類中屬性值來定義,后被標(biāo)定為 @Deprecated。
新的方式被定義在枚舉類 java.math.RoundingMode 中,有以下八種情況:
- CEILING :向正無窮大舍入
- DOWN :向零舍入
- FLOOR :向負(fù)無窮大舍入
- HALF_DOWN :向“最近的鄰居”舍入,除非兩個(gè)鄰居都等距,在這種情況下,將向下舍入
- HALF_EVEN :向“最近的鄰居”舍入,除非兩個(gè)鄰居都等距,在這種情況下,將向相鄰偶數(shù)舍入。
- HALF_UP :向“最近的鄰居”舍入,除非兩個(gè)鄰居都等距,在這種情況下,將向上舍入
- UNNECESSARY :舍入模式可以斷言所請(qǐng)求的操作具有準(zhǔn)確的結(jié)果,因此不需要舍入
- UP :舍入模式從零舍入(向著遠(yuǎn)離零的方向)
對(duì)此的理解可以參考上面的例子啦……
反思
雖說進(jìn)行了整理,但我也有一個(gè)困惑:是不是我理解這個(gè)舍入問題還是站在了十進(jìn)制的角度而計(jì)算機(jī)站在二進(jìn)制的角度呢?這兩種思維看待舍入問題會(huì)有哪些差別呢?
確實(shí)有點(diǎn)困惑,待我思索一下……有確定答案的讀者還請(qǐng)留言,感謝……
總結(jié)
以上是生活随笔為你收集整理的【Java】深入探讨Java数值舍入问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Python】Matplotlib使用
- 下一篇: 根据特殊EOF的序列判断比赛输赢(洛谷P