隨筆 - 9  文章 - 21  trackbacks - 0
          <2008年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          常用鏈接

          留言簿(1)

          隨筆分類(9)

          隨筆檔案(9)

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          第 3 天的問題

          被除數(shù)表示的是一天里的微秒數(shù);而除數(shù)表示的是一天里的毫秒數(shù)。這個程序會打印出什么呢?

          
          public class LongDivision{
              public static void main(String args[]){ 
                  final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000; 
                  final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000; 
                  System.out.println(MICROS_PER_DAY/MILLIS_PER_DAY); 
              } 
          } 
          
          

          第 3 天問題的解答

          這個題看起來相當(dāng)直觀。每天的毫秒數(shù)和每天的微秒數(shù)都是常量。為清楚起見,它們都被表示成積的形式。你可能想都沒想,就脫口而出,結(jié)果是1000。 遺憾的是,它打印的是5。這里到底發(fā)生了什么呢?

          原因

          問題在于常數(shù)MICROS_PER_DAY的計(jì)算"確實(shí)"溢出了。盡管計(jì)算的結(jié)果適合放入long中,并且其空間還有富余,但是這個結(jié)果并不適合放入int中。 這個計(jì)算完全是以int運(yùn)算來執(zhí)行的,并且只有在運(yùn)算完成之后,其結(jié)果才被提升到long,而此時已經(jīng)太遲了:計(jì)算已經(jīng)溢出了, 它返回的是一個小了200倍的數(shù)值。從int提升到long是一種拓寬原始類型轉(zhuǎn)換(widening primitive conversion), 它保留了(不正確的)數(shù)值。這個值之后被MILLIS_PER_DAY整除,而MILLIS_PER_DAY的計(jì)算是正確的,因?yàn)樗m合int運(yùn)算。這樣整除的結(jié)果就得到了5

          那么為什么計(jì)算會是以int運(yùn)算來執(zhí)行的呢?因?yàn)樗谐嗽谝黄鸬囊蜃佣际莍nt數(shù)值。當(dāng)你將兩個int數(shù)值相乘時, 你將得到另一個int數(shù)值。Java不具有目標(biāo)確定類型的特性,這是一種語言特性,其含義是指存儲結(jié)果的變量的類型會影響到計(jì)算所使用的類型

          解決辦法

          
          public class LongDivision{
              public static void main(String args[ ]){
                  final long MICROS_PER_DAY = 24L * 60 * 60 * 1000 * 1000;
                  final long MILLIS_PER_DAY = 24L * 60 * 60 * 1000;
                  System.out.println(MICROS_PER_DAY/MILLIS_PER_DAY);
              }
          }
          
          

          通過使用long常量來替代int常量作為每一個乘積的第一個因子,我們就可以很容易地訂正這個程序。這樣做可以強(qiáng)制表達(dá)式中所有的后續(xù)計(jì)算都用long運(yùn)作來完成。 盡管這么做只在MICROS_PER_DAY表達(dá)式中是必需的,但是在兩個乘積中都這么做是一種很好的方式。相似地,使用long作為乘積的"第一個"數(shù)值也并不總是必需的, 但是這么做也是一種很好的形式。在兩個計(jì)算中都以long數(shù)值開始可以很清楚地表明它們都不會溢出。下面的程序?qū)⒋蛴〕鑫覀兯谕?000

          第 3 天問題的總結(jié)

          這個教訓(xùn)很簡單:當(dāng)你在操作很大的數(shù)字時,千萬要提防溢出--它可是一個緘默殺手。 即使用來保存結(jié)果的變量已顯得足夠大,也并不意味著要產(chǎn)生結(jié)果的計(jì)算具有正確的類型。當(dāng)你拿不準(zhǔn)時,就使用long運(yùn)算來執(zhí)行整個計(jì)算。

          語言設(shè)計(jì)者從中可以吸取的教訓(xùn)是:也許降低緘默溢出產(chǎn)生的可能性確實(shí)是值得做的一件事。這可以通過對不會產(chǎn)生緘默溢出的運(yùn)算提供支持來實(shí)現(xiàn)。 程序可以拋出一個異常而不是直接溢出,就像Ada所作的那樣,或者它們可以在需要的時候自動地切換到一個更大的內(nèi)部表示上以防止溢出,就像Lisp所作的那樣。 這兩種方式都可能會遭受與其相關(guān)的性能方面的損失。 降低緘默溢出的另一種方式是支持目標(biāo)確定類型,但是這么做會顯著地增加類型系統(tǒng)的復(fù)雜度


          今天的問題

          它又會打印出什么呢?

          
          public class Elementary{
              public static void main(String[] args){
                  System.out.println(12345+5432l);
              }
          }
          
          
          posted on 2008-05-16 23:41 李四飛刀 閱讀(1255) 評論(1)  編輯  收藏 所屬分類: 每日一題

          FeedBack:
          # re: 第 4 天: 解答 -- 長整數(shù), 問題 -- 眼花繚亂 2008-05-17 00:01 ZelluX
          Java Puzzlers...  回復(fù)  更多評論
            
          主站蜘蛛池模板: 绿春县| 文成县| 霍邱县| 海林市| 古交市| 合肥市| 漯河市| 津南区| 布尔津县| 吴忠市| 榕江县| 衡东县| 株洲市| 舒城县| 武邑县| 社旗县| 河北省| 宜城市| 吐鲁番市| 垦利县| 洪江市| 深泽县| 汝南县| 称多县| 凤城市| 永城市| 益阳市| 西乡县| 西充县| 钟山县| 玉龙| 固原市| 康乐县| 广南县| 洛隆县| 洛扎县| 项城市| 浮梁县| 元氏县| 青铜峡市| 博湖县|