亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Java理論與實踐:您的小數點在哪?

2019-11-18 13:25:45
字體:
來源:轉載
供稿:網友

  java理論與實踐:您的小數點在哪?
          ——使用浮點數和小數中的技巧和陷阱
  作者:Brian Goetz 本文選自:IBM DW中國網站 2003年04月15日
    許多程序員在其整個開發生涯中都不曾使用定點或浮點數,可能的例外是,偶然在計時測試或基準測試程序中會用到。Java 語言和類庫支持兩類非整數類型 — IEEE 754 浮點(float 和 double,包裝類(wrapper class)為 Float 和 Double),以及任意精度的小數(java.math.BigDecimal)。在本月的 Java 理論和實踐中,Brian Goetz 探討了在 Java 程序中使用非整數類型時一些常碰到的陷阱和“gotcha”。
    雖然幾乎每種處理器和編程語言都支持浮點運算,但大多數程序員很少注重它。這輕易理解 — 我們中大多數很少需要使用非整數類型。除了科學計算和偶然的計時測試或基準測試程序,其它情況下幾乎都用不著它。同樣,大多數開發人員也輕易忽略 java.math.BigDecimal 所提供的任意精度的小數 — 大多數應用程序不使用它們。然而,在以整數為主的程序中有時確實會出人意料地需要表示非整型數據。例如,JDBC 使用 BigDecimal 作為 SQL DECIMAL 列的首選互換格式。
  IEEE 浮點
   Java 語言支持兩種基本的浮點類型:float 和 double,以及與它們對應的包裝類 Float 和 Double。它們都依據 IEEE 754 標準,該標準為 32 位浮點和 64 位雙精度浮點二進制小數定義了二進制標準。
    IEEE 754 用科學記數法以底數為 2 的小數來表示浮點數。IEEE 浮點數用 1 位表示數字的符號,用 8 位來表示指數,用 23 位來表示尾數,即小數部分。作為有符號整數的指數可以有正負之分。小數部分用二進制(底數 2)小數來表示,這意味著最高位對應著值 ?(2-1),第二位對應著 ?(2-2),依此類推。對于雙精度浮點數,用 11 位表示指數,52 位表示尾數。IEEE 浮點值的格式如圖 1 所示。
     1. IEEE 754 浮點數的格式
    因為用科學記數法可以有多種方式來表示給定數字,所以要規范化浮點數,以便用底數為 2 并且小數點左邊為 1 的小數來表示,按照需要調節指數就可以得到所需的數字。所以,例如,數 1.25 可以表示為尾數為 1.01,指數為 0:
    除了編碼所答應的值的標準范圍(對于 float,從 1.4e-45 到 3.4028235e+38),還有一些表示無窮大、負無窮大、-0 和 NaN(它代表“不是一個數字”)的非凡值。這些值的存在是為了在出現錯誤條件(譬如算術溢出,給負數開平方根,除以 0 等)下,可以用浮點值集合中的數字來表示所產生的結果?! ∵@些非凡的數字有一些不平常的特征。例如,0 和 -0 是不同值,但在比較它們是否相等時,被認為是相等的。用一個非零數去除以無窮大的數,結果等于 0。非凡數字 NaN 是無序的;使用 ==、< 和 > 運算符將 NaN 與其它浮點值比較時,結果為 false。假如 f 為 NaN,則即使 (f == f) 也會得到 false。假如想將浮點值與 NaN 進行比較,則使用 Float.isNaN() 方法。表 1 顯示了無窮大和 NaN 的一些屬性。
    表 1. 非凡浮點值的屬性
    表達式       結果
    Math.sqrt(-1.0) -> NaN
    .0 / 0.0     -> NaN
    1.0 / 0.0    -> 無窮大
    -1.0 / 0.0    -> 負無窮大
    NaN + 1.0    -> NaN
    無窮大 + 1.0   -> 無窮大
    無窮大 + 無窮大  -> 無窮大
    NaN > 1.0     -> false
    NaN == 1.0    -> false
    NaN < 1.0     -> false
    NaN == NaN    -> false
    0.0 == -0.01   -> true
    基本浮點類型和包裝類浮點有不同的比較行為
  使事情更糟的是,在基本 float 類型和包裝類 Float 之間,用于比較 NaN 和 -0 的規則是不同的。對于 float 值,比較兩個 NaN 值是否相等將會得到 false,而使用 Float.equals() 來比較兩個 NaN Float 對象會得到 true。造成這種現象的原因是,假如不這樣的話,就不可能將 NaN Float 對象用作 HashMap 中的鍵。類似的,雖然 0 和 -0 在表示為浮點值時,被認為是相等的,但使用 Float.compareTo() 來比較作為 Float 對象的 0 和 -0 時,會顯示 -0 小于 0。
    浮點中的危險
    由于無窮大、NaN 和 0 的非凡行為,當應用浮點數時,可能看似無害的轉換和優化實際上是不正確的。例如,雖然好象 0.0-f 很明顯等于 -f,但當 f 為 0 時,這是不正確的。還有其它類似的 gotcha,表 2 顯示了其中一些 gotcha。
    表 2. 無效的浮點假定
    這個表達式……   不一定等于……     當……
    0.0 - f     -f         f 為 0
    f < g      ! (f >= g)     f 或 g 為 NaN
    f == f     true         f 為 NaN
    f + g - g     f         g 為無窮大或 NaN
    舍入誤差
    浮點運算很少是精確的。雖然一些數字(譬如 0.5)可以精確地表示為二進制(底數 2)小數(因為 0.5 等于 2-1),但其它一些數字(譬如 0.1)就不能精確的表示。因此,浮點運算可能導致舍入誤差,產生的結果接近 — 但不等于 — 您可能希望的結果。例如,下面這個簡單的計算將得到 2.600000000000001,而不是 2.6:
  double s=0;
  for (int i=0; i<26; i++)
  s += 0.1;
  System.out.PRintln(s);
    類似的,.1*26 相乘所產生的結果不等于 .1 自身加 26 次所得到的結果。當將浮點數強制轉換成整數時,產生的舍入誤差甚至更嚴重,因為強制轉換成整數類型會舍棄非整數部分,甚至對于那些“看上去似乎”應該得到整數值的計算,也存在此類問題。例如,下面這些語句:
  double d = 29.0 * 0.01;
  System.out.println(d);
  System.out.println((int) (d * 100));
    將得到以下輸出:
  0.29
  28
    這可能不是您起初所期望的。
    浮點數比較指南
    由于存在 NaN 的不平常比較行為和在幾乎所有浮點計算中都不可避免地會出現舍入誤差,解釋浮點值的比較運算符的結果比較麻煩。
    最好完全避免使用浮點數比較。當然,這并不總是可能的,但您應該意識到要限制浮點數比較。假如必須比較浮點數來看它們是否相等,則應該將它們差的絕對值同一些預先選定的小正數進行比較,這樣您所做的就是測試它們是否“足夠接近”。(假如不知道基本的計算范圍,可以使用測試“abs(a/b - 1) < epsilon”,這種方法比簡單地比較兩者之差要更準確)。甚至測試看一個值是比零大還是比零小也存在危險 —“以為”會生成比零略大值的計算事實上可能由于積累的舍入誤差會生成略微比零小的數字。
    NaN 的無序性質使得在比較浮點數時更輕易發生錯誤。當比較浮點數時,圍繞無窮大和 NaN 問題,一種避免 gotcha 的經驗法則是顯式地測試值的有效性,而不是試圖排除無效值。在清單 1 中,有兩個可能的用于特性的 setter 的實現,該特性只能接受非負數值。第一個實現會接受 NaN,第二個不會。第二種形式比較好,因為它顯式地檢測了您認為有效的值的范圍。
    清單 1. 需要非負浮點值的較好辦法和較差辦法
  // Trying to test by exclusion -- this doesn't catch NaN or infinity
  public void setFoo(float foo) {
  if (foo < 0)
  throw new IllegalArgumentException(Float.toString(f));
  this.foo = foo;
  }
  // Testing by inclusion -- this does catch NaN
  public void setFoo(float foo) {
  if (foo >= 0 && foo < Float.INFINITY)
  this.foo = foo;
  else
  throw new IllegalArgumentException(Float.toString(f));
  }
  
    不要用浮點值表示精確值
  
    一些非整數值(如幾美元和幾美分這樣的小數)需要很精確。浮點數不是精確值,所以使用它們會導致舍入誤差。因此,使用浮點數來試圖表示象貨幣量這樣的精確數量不是一個好的想法。使用浮點數來進行美元和美分計算會得到災難性的后果。浮點數最好用來表示象測量值這類數值,這類值從一開始就不怎么精確。
  
    用于較小數的 BigDecimal
    從 JDK 1.3 起,Java 開發人員就有了另一種數值表示法來表示非整數:BigDecimal。BigDecimal 是標準的類,在編譯器中不需要非凡支持,它可以表示任意精度的小數,并對它們進行計算。在內部,可以用任意精度任何范圍的值和一個換算因子來表示 BigDecimal,換算因子表示左移小數點多少位,從而得到所期望范圍內的值。因此,用 BigDecimal 表示的數的形式為 :
               -scale
      unscaledValue*10  。
    用于加、減、乘和除的方法給 BigDecimal 值提供了算術運算。由于 BigDecimal 對象是不可變的,這些方法中的每一個都會產生新的 BigDecimal 對象。因此,因為創建對象的開銷,BigDecimal 不適合于大量的數學計算,但設計它的目的是用來精確地表示小數。假如您正在尋找一種能精確表示如貨幣量這樣的數值,則 BigDecimal 可以很好地勝任該任務。
    所有的 equals 方法都不能真正測試相等
    如浮點類型一樣,BigDecimal 也有一些令人希奇的行為。尤其在使用 equals() 方法來檢測數值之間是否相等時要小心。equals() 方法認為,兩個表示同一個數但換算值不同(例如,100.00 和 100.000)的 BigDecimal 值是不相等的。然而,compareTo() 方法會認為這兩個數是相等的,所以在從數值上比較兩個 BigDecimal 值時,應該使用 compareTo() 而不是 equals()。
    另外還有一些情形,任意精度的小數運

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产成人精品免高潮费视频| 国产精品国语对白| 欧美激情精品久久久久久黑人| 久久影院模特热| 另类少妇人与禽zozz0性伦| 九九热视频这里只有精品| 欧美午夜宅男影院在线观看| 色一区av在线| 91在线国产电影| 日韩中文字幕视频在线观看| 亚洲福利视频久久| 欧美激情xxxxx| 亚洲欧美一区二区精品久久久| 欧美日韩国产精品一区二区不卡中文| 欧美另类老女人| 久久影视电视剧凤归四时歌| 亚洲国产精品国自产拍av秋霞| 国模精品一区二区三区色天香| 久久69精品久久久久久国产越南| 精品国产成人在线| 国产精品日日摸夜夜添夜夜av| 欧美午夜片欧美片在线观看| 欧美巨乳在线观看| 欧美日韩另类字幕中文| 久久国产精彩视频| 深夜福利国产精品| 亚洲精品福利免费在线观看| 国精产品一区一区三区有限在线| 97碰在线观看| 日韩在线观看免费全集电视剧网站| 美女黄色丝袜一区| 亚洲深夜福利网站| 亚洲qvod图片区电影| 成人免费大片黄在线播放| 久久精品99无色码中文字幕| 黑丝美女久久久| 欧美另类极品videosbestfree| 国产欧美在线观看| 久久久久久久电影一区| 日本午夜精品理论片a级appf发布| 久久久久久网址| 国产精品女主播| 91免费人成网站在线观看18| 欧美一区二区三区艳史| 国产99久久久欧美黑人| 久久色在线播放| 亚洲无限乱码一二三四麻| 久久久精品在线| 欧美成人在线免费视频| 欧美体内谢she精2性欧美| 国产精品亚洲网站| 91欧美精品成人综合在线观看| 成人国产精品色哟哟| 国产精品h片在线播放| 国产精品美女无圣光视频| 高跟丝袜欧美一区| 91国自产精品中文字幕亚洲| 国产精品日韩在线观看| 国产精品午夜视频| 激情亚洲一区二区三区四区| 欧美日韩国产精品一区二区不卡中文| 欧美亚州一区二区三区| 国产精品草莓在线免费观看| 国产精品手机播放| 夜夜嗨av色一区二区不卡| 亚洲最大成人在线| 国产成人精品在线观看| 国产亚洲aⅴaaaaaa毛片| 97精品国产97久久久久久免费| 欧美性猛交xxxx免费看久久久| 亚洲成人网在线观看| 久久精品在线视频| 欧美精品在线网站| 日韩一区二区在线视频| 91精品国产九九九久久久亚洲| 日韩久久精品成人| 日韩在线播放av| 国外色69视频在线观看| 影音先锋欧美精品| 97热在线精品视频在线观看| 国产专区欧美专区| 自拍偷拍免费精品| 992tv成人免费影院| 91夜夜未满十八勿入爽爽影院| 91最新在线免费观看| 欧美另类69精品久久久久9999| 欧美性理论片在线观看片免费| 日本sm极度另类视频| 亚洲黄页视频免费观看| 欧美日韩中文在线观看| 亚洲国产高清福利视频| 97久久久久久| 午夜免费久久久久| 亚洲精品国产精品乱码不99按摩| 亚洲国产成人久久| 久久精品成人欧美大片| 久久激情视频久久| 91在线观看免费| 久久久久免费精品国产| 国产精自产拍久久久久久| 亚洲欧美国产精品专区久久| 91久久夜色精品国产网站| 欧美黑人一区二区三区| 国产日韩精品入口| 亚洲电影免费观看| 91在线观看免费高清| 久久激情视频免费观看| 亚洲毛片在线观看.| 亚洲精品小视频在线观看| 日韩一二三在线视频播| 伊人久久久久久久久久久久久| 色综合久综合久久综合久鬼88| 91精品视频一区| 黑人巨大精品欧美一区二区一视频| 日韩欧美精品免费在线| 久久久成人的性感天堂| 自拍偷拍亚洲精品| 国产成人啪精品视频免费网| 久久国产一区二区三区| 国产精品成av人在线视午夜片| 中文综合在线观看| 九色成人免费视频| 最近日韩中文字幕中文| 中文亚洲视频在线| 精品久久久久久久中文字幕| 国产美女精品视频| 亚州成人av在线| 久久久噜噜噜久久| 一区二区在线免费视频| 日本午夜精品理论片a级appf发布| 欧美日韩美女在线观看| 日韩欧美a级成人黄色| 清纯唯美亚洲激情| 亚洲电影天堂av| 亚洲综合社区网| 亚洲激情视频在线观看| 亚洲成人网在线观看| 91久久夜色精品国产网站| 国产精品极品美女粉嫩高清在线| 国产精品扒开腿做爽爽爽的视频| 亚洲va欧美va在线观看| 疯狂做受xxxx欧美肥白少妇| 原创国产精品91| 国产美女精品视频免费观看| 欧美精品激情在线观看| 成人欧美一区二区三区在线湿哒哒| 日韩av电影在线免费播放| 日韩视频免费中文字幕| 亚洲女人被黑人巨大进入| 国产精品日韩专区| 国产欧美 在线欧美| 亚洲成人教育av| 日韩免费在线看| 亚洲日本欧美日韩高观看| 亚洲欧美一区二区三区久久| 欧美一级大片在线观看| 91亚洲国产成人久久精品网站| 国产精品激情av电影在线观看| 国产成人精品视频在线| 精品一区二区三区电影| 精品视频—区二区三区免费| 中文字幕成人在线| 欧美肥臀大乳一区二区免费视频| 欧美人在线观看|