国产TS紫迹丝袜高跟鞋在线,一区二区三区国产自产视频免费,67pao国产人成视频,午国产午夜激无码毛片不卡

愛碼網(wǎng)專注于資源免費(fèi)下載

Java解惑之表達(dá)式謎題(謎題2:找零時刻)

謎題2:找零時刻

Java解惑之表達(dá)式謎題(謎題2:找零時刻)-第1張圖片

請考慮下面這段話所描述的問題: 

Tom在一家汽車配件商店購買了一個價(jià)值$1.10的火花塞,但是他錢包中都是兩美元一張的鈔票。如果他用一張兩美元的鈔票支付這個火花塞,那么應(yīng)該找給他

多少零錢呢? 下面是一個試圖解決上述問題的程序,它會打印出什么呢?  

public class Change{
        public static void main(String args[]){
                 System.out.println(2.00 - 1.10);
            }
}

你可能會很天真地期望該程序能夠打印出0.90,但是它如何才能知道你想要打印小數(shù)點(diǎn)后兩位小數(shù)呢? 

如果你對在Double.toString文檔中所設(shè)定的將double類型的值轉(zhuǎn)換為字符串的規(guī)則有所了解,你就會知道該程序打印出來的小數(shù),是足以將double類型的

值與最靠近它的臨近值區(qū)分出來的最短的小數(shù),它在小數(shù)點(diǎn)之前和之后都至少有一位。因此,看起來,該程序應(yīng)該打印0.9是合理的。 這么分析可能顯得很合理,但是并不正確。如果你運(yùn)行該程序,你就會發(fā)現(xiàn)它打印的是0.8999999999999999。 

問題在于1.1這個數(shù)字不能被精確表示成為一個double,因此它被表示成為最接近它的double值。該程序從2中減去的就是這個值。遺憾的是,這個計(jì)算的結(jié)果并不是最接近0.9的double值。表示結(jié)果的double值的最短表示就是你所看到的打印出來的那個可惡的數(shù)字。 更一般地說,問題在于并不是所有的小數(shù)都可以用二進(jìn)制浮點(diǎn)數(shù)來精確表示的。 如果你正在用的是JDK 5.0或更新的版本,那么你可能會受其誘惑,通過使用printf工具來設(shè)置輸出精度的方訂正該程序:  

//拙劣的解決方案——仍舊是使用二進(jìn)制浮點(diǎn)數(shù)

System.out.printf("%.2f%n",2.00 - 1.10);

這條語句打印的是正確的結(jié)果,但是這并不表示它就是對底層問題的通用解決方案:它使用的仍舊是二進(jìn)制浮點(diǎn)數(shù)的double運(yùn)算。浮點(diǎn)運(yùn)算在一個范圍很廣的值域上提供了很好的近似,但是它通常不能產(chǎn)生精確的結(jié)果。二進(jìn)制浮點(diǎn)對于貨幣計(jì)算是非常不適合的,因?yàn)樗豢赡軐?.1——或者10的其它任何次負(fù)冪—— 精確表示為一個長度有限的二進(jìn)制小數(shù) 


解決該問題的一種方式是使用某種整數(shù)類型,例如int或long,并且以分為單位來執(zhí)行計(jì)算。如果你采納了此路線,請確保該整數(shù)類型大到足夠表示在程序中

你將要用到的所有值。對這里舉例的謎題來說,int就足夠了。下面是我們用int類型來以分為單位表示貨幣值后重寫的println語句。這個版本將打印出正確答案90分:  

System.out.println((200 - 110) + "cents");

解決該問題的另一種方式是使用執(zhí)行精確小數(shù)運(yùn)算的BigDecimal。它還可以通過JDBC與SQL DECIMAL類型進(jìn)行互操作。這里要告誡你一點(diǎn): 一定要用BigDecimal(String)構(gòu)造器,而千萬不要用BigDecimal(double)。后一個構(gòu)造器將用它的參數(shù)的“精確”值來創(chuàng)建一個實(shí)例:new BigDecimal(.1)將返回一個

表示0.100000000000000055511151231257827021181583404541015625的BigDecimal。通過正確使用BigDecimal,程序就可以打印出我們所期望的結(jié)果0.90:  

import java.math.BigDecimal; public class Change1{
        public static void main(String args[]){
                             System.out.println(new BigDecimal("2.00").
                                         subtract(new BigDecimal("1.10")));
            }
}

這個版本并不是十分地完美,因?yàn)镴ava并沒有為BigDecimal提供任何語言上的支持。使用BigDecimal的計(jì)算很有可能比那些使用原始類型的計(jì)算要慢一些,對某些大量使用小數(shù)計(jì)算的程序來說,這可能會成為問題,而對大多數(shù)程序來說,這顯得一點(diǎn)也不重要。 總之, 在需要精確答案的地方,要避免使用float和double;對于貨幣計(jì)算,要使用int、long或BigDecimal。對于語言設(shè)計(jì)者來說,應(yīng)該考慮對小數(shù)運(yùn)算提供語言支持。一種方式是提供對操作符重載的有限支持,以使得運(yùn)算符可以被塑造為能夠?qū)?shù)值引用類型起作用,例如BigDecimal。另一種方式是提供原始的小數(shù)類型,就像COBOL與PL/I所作的一樣。 


本文鏈接:http://fangxuan.com.cn/article/279.html

網(wǎng)友評論

熱門文章
隨機(jī)文章
熱門標(biāo)簽
側(cè)欄廣告位