一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

BigDecimal使用失誤的原因分析

Android編程精選 ? 來源:稀土掘金 ? 作者:Android編程精選 ? 2022-07-10 14:35 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

背景

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

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

事故

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

問題描述

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

事故級別

P0

事故過程

如下:

13:44,接到報(bào)警,訂單支付失敗,支付可用率降至 60%

13:50,迅速回滾上線代碼,恢復(fù)正常

14:20,review 代碼,預(yù)發(fā)布驗(yàn)證發(fā)現(xiàn)問題點(diǎn)

14:58,修改問題代碼上線,線上恢復(fù)

故障原因

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

原因分析

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

publicstaticvoidmain(String[]args){
BigDecimalbigDecimal=newBigDecimal(88);
System.out.println(bigDecimal);
bigDecimal=newBigDecimal("8.8");
System.out.println(bigDecimal);
bigDecimal=newBigDecimal(8.8);
System.out.println(bigDecimal);
}

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

64b88216-ed69-11ec-ba43-dac502259ad0.png

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

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

publicstaticlongdoubleToLongBits(doublevalue){
longresult=doubleToRawLongBits(value);
//CheckforNaNbasedonvaluesofbitfields,maximum
//exponentandnonzerosignificand.
if(((result&DoubleConsts.EXP_BIT_MASK)==
DoubleConsts.EXP_BIT_MASK)&&
(result&DoubleConsts.SIGNIF_BIT_MASK)!=0L)
result=0x7ff8000000000000L;
returnresult;
}

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

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

64db7bf4-ed69-11ec-ba43-dac502259ad0.png

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

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

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

當(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)無限循環(huán)或者超過浮點(diǎn)數(shù)尾數(shù)的長度。

總結(jié)

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

編輯:黃飛

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 浮點(diǎn)數(shù)
    +關(guān)注

    關(guān)注

    0

    文章

    61

    瀏覽量

    16130
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4900

    瀏覽量

    70698
  • string
    +關(guān)注

    關(guān)注

    0

    文章

    40

    瀏覽量

    4910

原文標(biāo)題:BigDecimal使用不當(dāng),造成P0事故!

文章出處:【微信號:AndroidPush,微信公眾號:Android編程精選】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點(diǎn)推薦

    關(guān)于鍍銅表面粗糙問題原因分析

    本帖最后由 gk320830 于 2015-3-7 10:15 編輯 關(guān)于鍍銅表面粗糙問題原因分析可能原因如下:  鍍銅槽本身的問題  1、陽極問題:成分含量不當(dāng)導(dǎo)致產(chǎn)生雜質(zhì)  2、光澤劑
    發(fā)表于 11-07 11:21

    電池膨脹原因分析

    電池膨脹原因分析 一般電池電池膨脹的主要原因是:
    發(fā)表于 10-21 10:41 ?1184次閱讀

    LED死燈的原因分析探討

    LED死燈現(xiàn)象的原因有兩種情況,本文將詳細(xì)的說明及分析原因
    發(fā)表于 05-20 17:36 ?1992次閱讀

    某型導(dǎo)彈射手失誤信號的時(shí)頻分析研究

    在某型導(dǎo)彈飛行訓(xùn)練中,射手失誤后,對信號的處理不能準(zhǔn)確得出失誤發(fā)生的時(shí)間、失誤的程度、失誤原因。針對這個(gè)問題,
    發(fā)表于 11-14 11:10 ?29次下載
    某型導(dǎo)彈射手<b class='flag-5'>失誤</b>信號的時(shí)頻<b class='flag-5'>分析</b>研究

    壓縮機(jī)故障原因分析PDF

    壓縮機(jī)故障原因分析PDF空調(diào)維修技術(shù)壓縮機(jī)故障原因分析PDF空調(diào)維修技術(shù)壓縮機(jī)故障原因分析PDF
    發(fā)表于 04-28 11:45 ?6次下載

    導(dǎo)致煙霧報(bào)警器失誤的主要原因有哪些?詳細(xì)分析

    安裝煙霧報(bào)警器主要是為了防止我們在不經(jīng)意間未能及時(shí)發(fā)現(xiàn)火災(zāi)或者起煙霧將引發(fā)火災(zāi)的一種防護(hù)措施。不過我們偶爾會(huì)發(fā)現(xiàn)家里安裝了有些年頭的煙霧報(bào)警器會(huì)時(shí)不時(shí)響一下,但是檢查有沒有發(fā)現(xiàn)異常。這是什么原因呢?是什么導(dǎo)致煙霧報(bào)警器失誤呢?
    的頭像 發(fā)表于 04-11 16:31 ?1.6w次閱讀

    BigDecimal實(shí)際開發(fā)的三坑是什么

    采用String 類型的構(gòu)造參數(shù)。如果必須要使用double,則可使用Double.toString(double) 方法轉(zhuǎn)換成String, 再采用Bigdecimal的構(gòu)造函數(shù).
    的頭像 發(fā)表于 02-16 14:39 ?922次閱讀

    什么是PFMEA中有效的原因分析呢?

    多數(shù)工廠的PFMEA的原因為“違規(guī)作業(yè),未按作業(yè)指導(dǎo)書作業(yè),新員工,操作失誤,沒有培訓(xùn),員工技能不足,原材料不良,設(shè)備損壞等”。
    發(fā)表于 03-31 11:39 ?1187次閱讀

    變頻電機(jī)振動(dòng)原因分析

    變頻電機(jī)振動(dòng)原因分析? 變頻電機(jī)振動(dòng)是一種常見的故障現(xiàn)象,往往會(huì)造成設(shè)備的不穩(wěn)定性和降低設(shè)備的使用壽命。因此,對于變頻電機(jī)振動(dòng)的原因進(jìn)行分析和解決是非常必要的。本文將從以下幾個(gè)方面對變
    的頭像 發(fā)表于 08-28 17:43 ?3604次閱讀

    bigdecimal轉(zhuǎn)string類型

    BigDecimal轉(zhuǎn)換為String類型是在Java編程中常常遇到的一個(gè)問題。BigDecimal是Java中用于表示高精度十進(jìn)制數(shù)的類,而String則是用于表示文本字符串的數(shù)據(jù)類型。在某些
    的頭像 發(fā)表于 11-30 11:09 ?6962次閱讀

    怎么把bigdecimal轉(zhuǎn)成string

    BigDecimal轉(zhuǎn)換為String是一項(xiàng)常見的任務(wù),在Java的開發(fā)中經(jīng)常會(huì)涉及到將數(shù)值進(jìn)行格式化,并在不同的環(huán)境中傳遞。本文將詳解以下幾個(gè)方面的內(nèi)容: 什么是BigDecimal
    的頭像 發(fā)表于 11-30 11:11 ?2156次閱讀

    bigdecimal轉(zhuǎn)string類型避免空指針

    在Java中,BigDecimal是用于處理高精度數(shù)字計(jì)算的類。它提供了一種有效的方法來避免使用浮點(diǎn)數(shù)的精確度損失問題。然而,在將BigDecimal對象轉(zhuǎn)換為String類型時(shí),需要特別小心以避
    的頭像 發(fā)表于 11-30 11:12 ?3397次閱讀

    bigdecimal轉(zhuǎn)字符串保留兩位小數(shù)

    BigDecimals是Java中用于表示任意精度的十進(jìn)制數(shù)的類。在許多應(yīng)用程序中,可能需要將一個(gè)BigDecimal轉(zhuǎn)換為字符串并保留兩位小數(shù)。在本文中,我們將探討如何使用BigDecimal
    的頭像 發(fā)表于 11-30 11:18 ?5068次閱讀

    bigdecimal的加減乘除java

    BigDecimal是Java中提供的一個(gè)用于精確計(jì)算的類,它可以實(shí)現(xiàn)浮點(diǎn)數(shù)的精確加減乘除運(yùn)算,避免了在使用浮點(diǎn)數(shù)進(jìn)行計(jì)算時(shí)可能出現(xiàn)的舍入誤差。 首先,我們需要明確一點(diǎn),浮點(diǎn)數(shù)在計(jì)算機(jī)中是以二進(jìn)制
    的頭像 發(fā)表于 11-30 11:19 ?1918次閱讀

    bigdecimal是什么數(shù)據(jù)類型

    BigDecimal是Java編程語言中的一個(gè)類,用于表示任意精度的十進(jìn)制數(shù)。它是在數(shù)值計(jì)算方面提供更高精度和更多功能的一個(gè)解決方案。常規(guī)的浮點(diǎn)數(shù)類型(如float和double)有精度限制,可能會(huì)
    的頭像 發(fā)表于 11-30 11:21 ?3689次閱讀