<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          BigDecimal使用不當(dāng),造成P0事故!

          共 2047字,需瀏覽 5分鐘

           ·

          2022-06-09 02:42

          文章來(lái)源:https://c1n.cn/MSqAy

          背景

          我們?cè)谑褂媒痤~計(jì)算或者展示金額的時(shí)候經(jīng)常會(huì)使用 BigDecimal,也是涉及金額時(shí)非常推薦的一個(gè)類(lèi)型。

          BigDecimal 自身也提供了很多構(gòu)造器方法,這些構(gòu)造器方法使用不當(dāng)可能會(huì)造成不必要的麻煩甚至是金額損失,從而引起事故資損。

          事故

          接下來(lái)我們看下收銀臺(tái)出的一起事故。

          問(wèn)題描述

          收銀臺(tái)計(jì)算商品金額報(bào)錯(cuò),導(dǎo)致訂單無(wú)法支付。

          事故級(jí)別

          P0

          事故過(guò)程

          如下:

          • 13:44,接到報(bào)警,訂單支付失敗,支付可用率降至 60%
          • 13:50,迅速回滾上線代碼,恢復(fù)正常
          • 14:20,review 代碼,預(yù)發(fā)布驗(yàn)證發(fā)現(xiàn)問(wèn)題點(diǎn)
          • 14:58,修改問(wèn)題代碼上線,線上恢復(fù)

          故障原因

          BigDecimal 在金額計(jì)算中丟失精度。

          原因分析

          首先我們先用一段代碼復(fù)現(xiàn)問(wèn)題根源,如下所示:

          public?static?void?main(String[]?args)?{
          ????BigDecimal?bigDecimal=new?BigDecimal(88);
          ????System.out.println(bigDecimal);
          ????bigDecimal=new?BigDecimal("8.8");
          ????System.out.println(bigDecimal);
          ????bigDecimal=new?BigDecimal(8.8);
          ????System.out.println(bigDecimal);
          }

          執(zhí)行結(jié)果如下:

          通過(guò)測(cè)試發(fā)現(xiàn),當(dāng)使用 double 或者 float 這些浮點(diǎn)數(shù)據(jù)類(lèi)型時(shí),會(huì)丟失精度,String、int 則不會(huì),這是為什么呢?

          我們點(diǎn)開(kāi)構(gòu)造器方法看下源碼:

          public?static?long?doubleToLongBits(double?value)?{
          ????long?result?=?doubleToRawLongBits(value);
          ????//?Check?for?NaN?based?on?values?of?bit?fields,?maximum
          ????//?exponent?and?nonzero?significand.
          ????if?(?((result?&?DoubleConsts.EXP_BIT_MASK)?==
          ??????????DoubleConsts.EXP_BIT_MASK)?&&
          ?????????(result?&?DoubleConsts.SIGNIF_BIT_MASK)?!=?0L)
          ????????result?=?0x7ff8000000000000L;
          ????return?result;
          }

          問(wèn)題就處在 doubleToRawLongBits 這個(gè)方法上,在 jdk 中 double 類(lèi)(float 與 int 對(duì)應(yīng))中提供了 double 與 long 轉(zhuǎn)換,doubleToRawLongBits 就是將 double 轉(zhuǎn)換為 long,這個(gè)方法是原始方法(底層不是 java 實(shí)現(xiàn),是 c++ 實(shí)現(xiàn)的)。

          double 之所以會(huì)出問(wèn)題,是因?yàn)樾?shù)點(diǎn)轉(zhuǎn)二進(jìn)制丟失精度。

          BigDecimal 在處理的時(shí)候把十進(jìn)制小數(shù)擴(kuò)大 N 倍讓它在整數(shù)上進(jìn)行計(jì)算,并保留相應(yīng)的精度信息。

          float 和 double 類(lèi)型,主要是為了科學(xué)計(jì)算和工程計(jì)算而設(shè)計(jì)的,之所以執(zhí)行二進(jìn)制浮點(diǎn)運(yùn)算,是為了在廣泛的數(shù)值范圍上提供較為精確的快速近和計(jì)算。

          并沒(méi)有提供完全精確的結(jié)果,所以不應(yīng)該被用于精確的結(jié)果的場(chǎng)合。

          當(dāng)浮點(diǎn)數(shù)達(dá)到一定大的數(shù),就會(huì)自動(dòng)使用科學(xué)計(jì)數(shù)法,這樣的表示只是近似真實(shí)數(shù)而不等于真實(shí)數(shù)。

          當(dāng)十進(jìn)制小數(shù)位轉(zhuǎn)換二進(jìn)制的時(shí)候也會(huì)出現(xiàn)無(wú)限循環(huán)或者超過(guò)浮點(diǎn)數(shù)尾數(shù)的長(zhǎng)度。

          總結(jié)

          所以,在涉及到精度計(jì)算的過(guò)程中,我們盡量使用 String 類(lèi)型來(lái)進(jìn)行轉(zhuǎn)換。

          我們創(chuàng)建了一個(gè)高質(zhì)量的技術(shù)交流群,與優(yōu)秀的人在一起,自己也會(huì)優(yōu)秀起來(lái),趕緊點(diǎn)擊加群,享受一起成長(zhǎng)的快樂(lè)。另外,如果你最近想跳槽的話,年前我花了2周時(shí)間收集了一波大廠面經(jīng),節(jié)后準(zhǔn)備跳槽的可以點(diǎn)擊這里領(lǐng)取

          推薦閱讀

          ··································

          你好,我是程序猿DD,10年開(kāi)發(fā)老司機(jī)、阿里云MVP、騰訊云TVP、出過(guò)書(shū)創(chuàng)過(guò)業(yè)、國(guó)企4年互聯(lián)網(wǎng)6年從普通開(kāi)發(fā)到架構(gòu)師、再到合伙人。一路過(guò)來(lái),給我最深的感受就是一定要不斷學(xué)習(xí)并關(guān)注前沿。只要你能堅(jiān)持下來(lái),多思考、少抱怨、勤動(dòng)手,就很容易實(shí)現(xiàn)彎道超車(chē)!所以,不要問(wèn)我現(xiàn)在干什么是否來(lái)得及。如果你看好一個(gè)事情,一定是堅(jiān)持了才能看到希望,而不是看到希望才去堅(jiān)持。相信我,只要堅(jiān)持下來(lái),你一定比現(xiàn)在更好!如果你還沒(méi)什么方向,可以先關(guān)注我,這里會(huì)經(jīng)常分享一些前沿資訊,幫你積累彎道超車(chē)的資本。

          點(diǎn)擊領(lǐng)取2022最新10000T學(xué)習(xí)資料
          瀏覽 21
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久婷婷秘 精品日产538 | 91人妻日韩人妻无码专区精品 | 成人A片一级片 | 日韩成人三级 | 18禁成人黄色 |