国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

js浮點數(shù)四則運算精度丟失以及toFixed()精度丟失解決方法

這篇具有很好參考價值的文章主要介紹了js浮點數(shù)四則運算精度丟失以及toFixed()精度丟失解決方法。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

一、js浮點數(shù)計算精度丟失的一些例子

1、四則運算精度丟失:

0.1+0.2 = 0.30000000000000004 
 
0.3 - 0.2 = 0.09999999999999998
 
10.22*100 = 1022.0000000000001
 
2.4/0.8 = 2.9999999999999996
 
32.2*100 = 3220.0000000000005
 
32.2*1000 = 32200.000000000004
 
(32.2*100 + 3.14*100) / 100 = 35.34 // 這里的精度怎么又不丟失了?
 
32.3*100 = 3229.9999999999995
 
32.3*1000 = 32299.999999999996
 
...

2、toFixed() 四舍五入精度丟失:

(1.335).toFixed(2); // '1.33'
(6.265).toFixed(2); // '6.26'

二、浮點數(shù)計算精度丟失的原因

js采用64位浮點數(shù)表示法(幾乎所有現(xiàn)代編程語言所采用),這是一種二進制表示法。二進制浮點數(shù)表示法并不能精確表示類似 0.1 這樣簡單的數(shù)字。

這個問題不只在js中才會出現(xiàn),在任何使用二進制浮點數(shù)的編程語言中都會出現(xiàn)。

JavaScript的未來版本或許會支持十進制數(shù)字類型以避免精度丟失的問題。

三、解決辦法

1、使用 big.js(如果有大量連續(xù)的計算推薦使用)

  • 既解決了浮點數(shù)計算精度丟失問題,又解決了 toFixed() 四舍五入精度丟失問題。
  • big.jsbig.js, bignumber.js, decimal.js 三姐妹中功能最少的,但也是體積最小的,壓縮版只有3k,對于處理js精度丟失已經(jīng)足夠用了。
  import Big from 'big.js'
 
  // 運算
  const plus = Big(0.1).plus(0.2); // 加
  const minus = Big(0.3).minus(0.1); // 減
  const mul = Big(10.22).times(100); // 乘
  const div = Big(2.4).div(0.8); // 除
 
  // toFixed
  const fixed = new Big(6.265).toFixed(2); // 6.27
 
  console.log(
    plus.toNumber(),
    minus.toNumber(),
    mul.toNumber(),
    div.toNumber()
  )
  // 0.3 0.2 1022 3

2、解決四則運算精度丟失問題

方法1:沒有具體要求保留幾位小數(shù)的,最簡單的方法是直接用 toFixed()

從上面四則運算精度丟失的例子可以看到,四則運算的精度丟失主要會出現(xiàn)很多位 0 或很多位 9。

function precision(val) {
  return +val.toFixed(8);
}
 
precision(0.1 + 0.2)
方法2:有具體要求精確到第幾位,用科學計數(shù)法對運算結(jié)果進行四舍五入

MDN 已經(jīng)給出了具體代碼(也是利用“科學計數(shù)法”擴大 10 的 n 次不會出現(xiàn)精度丟失的特性):

function round(number, precision) {
    return Math.round(+number + 'e' + precision) / Math.pow(10, precision);
}
 
round(1.005, 2);    //1.01
round(1.002, 2);    //1

或者:

/**
 * Decimal adjustment of a number.
 *
 * @param {String}  type  The type of adjustment.
 * @param {Number}  value The number.
 * @param {Integer} exp   The exponent (the 10 logarithm of the adjustment base).
 * @returns {Number}      The adjusted value.
 */
function decimalAdjust(type, value, exp) {
    // If the exp is undefined or zero...
    if (typeof exp === 'undefined' || +exp === 0) {
        return Math[type](value);
    }
    value = +value;
    exp = +exp;
    // If the value is not a number or the exp is not an integer...
    if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
        return NaN;
    }
    // Shift
    value = value.toString().split('e');
    value = Math[type](+(value[0] + 'e' + (value[1] ? +value[1] - exp : -exp)));
    // Shift back
    value = value.toString().split('e');
    value = +(value[0] + 'e' + (value[1] ? +value[1] + exp : exp));
    return value;
}
 
export default {
    round: (value, exp) => {
        return decimalAdjust('round', value, exp);
    },
    floor: (value, exp) => {
        return decimalAdjust('floor', value, exp);
    },
    ceil: (value, exp) => {
        return decimalAdjust('ceil', value, exp);
    }
};
實現(xiàn)原理:
比如 1022.0000000000001 要保留2位小數(shù),先用 e2 把這個數(shù)擴大 100 倍,
再用 Math.round(), Math.floor(), Math.ceil() 取整,然后再用 e-2 縮小回來。
使用方法:
Decimal.round(val, precision)
 
console.log(Decimal.round(1.13265, -3))  //1.133
console.log(Decimal.round(3.17, -3))  //3.17
console.log(Decimal.round(0.1+0.2, -3))  //0.3
console.log(Decimal.round(3.17))  //3
console.log(Decimal.round(3.17, 0))  //3
console.log(Decimal.round(31216, 1))  //31220
console.log(Decimal.round(31213, 2))  //31200

precision 可選值:不傳,0,負數(shù),正數(shù)。

  • 不傳、0: 精確到整數(shù)。
  • 正數(shù): 1就是個位為0,十位是個位四舍五入的值。
  • 負數(shù): 精確到小數(shù)點后幾位

3、解決 toFixed() 精度丟失問題:重寫 toFixed 方法(重點?。。。。?/h4>
function toFixed(number, precision = 2) {
  number = Math.round(+number + 'e' + precision) / Math.pow(10, precision) + '';
  let s = number.split('.');
  if ((s[1] || '').length < precision) {
    s[1] = s[1] || '';
    s[1] += new Array(precision - s[1].length).fill('0').join('');
  }
  return s.join('.');
}
 
toFixed(6) // '6.00'

四、判斷小數(shù)是否相等

function epsEqu(x,y) {  
  return Math.abs(x - y) < Math.pow(2, -52);
  // 因為 Number.EPSILON === Math.pow(2, -52),所以也可以這么寫:
  // return Math.abs(x - y) < Number.EPSILON;
}
// 舉例
0.1 + 0.2 === 0.3 // false
epsEqu(0.1 + 0.2, 0.3) // true
小數(shù)比較時,要給它一個誤差范圍,在誤差范圍內(nèi)的都算相等。

五、其他由浮點數(shù)引起的問題

parseInt(0.0000008) // -> 8

六、項目內(nèi)實際應(yīng)用

js精度丟失解決辦法,javascript,前端,開發(fā)語言

在列表上勾選5個涉案金額為0.055萬元的案件,進行批量結(jié)案操作,在批量結(jié)案中,有一個減損值的計算,通過計算勾選案件涉案金額平均值-用戶所填寫的結(jié)案支付金額得出減損值,那么問題出現(xiàn)了,我在結(jié)案支付金額填寫為0.055,正常計算的話結(jié)果應(yīng)改為0,可是截圖卻如圖所示:
js精度丟失解決辦法,javascript,前端,開發(fā)語言
這里的業(yè)務(wù)代碼為:

// 批量結(jié)案涉案金額取勾選數(shù)據(jù)的平均值
const amountInvolved = selectedRows.reduce((c, R) => c + (R.amountInvolved - 0), 0) / selectedRows.length

//計算減損值
OnchangeMoney(value) {
      this.mdl.impairmentValue = this.req.amountInvolved - value
},

打斷點發(fā)現(xiàn)是計算平均值amountInvolved時出現(xiàn)了浮點數(shù),那么封裝一個方法:文章來源地址http://www.zghlxwxcb.cn/news/detail-753643.html

function strip(num, precision = 12) { 
  return +parseFloat(num.toPrecision(precision)); 
}  
為什么選擇 12 做為默認精度?
這是一個經(jīng)驗的選擇,一般選12就能解決掉大部分0001和0009問題,
而且大部分情況下也夠用了,如果你需要更精確可以調(diào)高。
  • 處理平均數(shù)計算:
// 批量結(jié)案涉案金額取勾選數(shù)據(jù)的平均值
const amountInvolved = this.strip(
      selectedRows.reduce((c, R) => c + (R.amountInvolved - 0), 0) / selectedRows.length
 )
  • 運行之后發(fā)現(xiàn)還是有浮點數(shù),打斷點是計算差值是也出現(xiàn)了浮點數(shù),解決:
//計算金額
OnchangeMoney(value) {
   this.mdl.impairmentValue = this.strip(this.req.amountInvolved - value)
},

參考(JS 計算最小值,最大值,平均值,標準差,中位數(shù)):

      // @numbers 包含所有數(shù)字的一維數(shù)組
      // @digit 保留數(shù)值精度小數(shù)位數(shù),默認兩位小數(shù)
      function getBebeQ(numbers, digit = 2) {
        // 修復(fù)js浮點數(shù)精度誤差問題
        const formulaCalc = function formulaCalc(formula, digit) {
          let pow = Math.pow(10, digit);
          return parseInt(formula * pow, 10) / pow;
        };
        let len = numbers.length;
        let sum = (a, b) => formulaCalc(a + b, digit);
        let max = Math.max.apply(null, numbers);
        let min = Math.min.apply(null, numbers);
        // 平均值
        let avg = numbers.reduce(sum) / len;
        // 計算中位數(shù)
        // 將數(shù)值從大到小順序排列好,賦值給新數(shù)組用于計算中位數(shù)
        let sequence = [].concat(numbers).sort((a,b) => b-a);
        let mid = len & 1 === 0 ?
          (sequence[len/2] + sequence[len/2+1]) / 2 :
          sequence[(len+1)/2];
        // 計算標準差
        // 所有數(shù)減去其平均值的平方和,再除以數(shù)組個數(shù)(或個數(shù)減一,即變異數(shù))再把所得值開根號
        let stdDev = Math.sqrt(numbers.map(n=> (n-avg) * (n-avg)).reduce(sum) / len);
        return {
          max,
          min,
          avg: avg.toFixed(digit),
          mid: parseFloat(mid).toFixed(digit),
          stdDev : stdDev.toFixed(digit)
        }
      }

到了這里,關(guān)于js浮點數(shù)四則運算精度丟失以及toFixed()精度丟失解決方法的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • js精度丟失的問題

    1.js精度丟失的常見問題,從常見的浮點型進行計算,到位數(shù)很長的munber類型進行計算都會造成精度丟失的問題, 首先我們看一個問題: 那么js為什么會出現(xiàn)精度丟失的問題: 計算機的二進制實現(xiàn)和位數(shù)限制有些數(shù)無法有限表示。就像一些無理數(shù)不能有限表示,如 圓周率 3.1

    2024年02月14日
    瀏覽(27)
  • MyBatis-Plus主鍵策略(雪花算法16位長度的整型id,解決默認雪花算法生成19位長度id導致JS精度丟失問題)

    js表達的最大整數(shù)2的53次方減1,精度丟失后面幾位全是0! 如果內(nèi)置支持不滿足你的需求,可實現(xiàn) IKeyGenerator 接口來進行擴展. 舉個栗子 #方式一:使用配置類 #方式二:通過 MybatisPlusPropertiesCustomizer 自定義 #方式一: XML 配置 #方式二:注解配置 官方示例 官方id generator示例 htt

    2023年04月08日
    瀏覽(24)
  • java數(shù)據(jù)類型的轉(zhuǎn)換以及精度丟失

    java數(shù)據(jù)類型的轉(zhuǎn)換以及精度丟失

    float存儲需求是4字節(jié)(32位), 其中1位最高位是符號位,中間8位表示階位,后32位表示值 double存儲需求是8字節(jié)(64為),其中1位最高位是符號位,中間11位表示階位,后52位表示值 精度丟失就是我們的位數(shù)不夠表示我們整個數(shù)值了 問題原因: 首先計算機進行的是二進制運算,

    2023年04月13日
    瀏覽(32)
  • Unity - 記錄解決 部分手機設(shè)備上 浮點精度 不足 導致 UV 采樣斷層嚴重的 BUG

    Unity - 記錄解決 部分手機設(shè)備上 浮點精度 不足 導致 UV 采樣斷層嚴重的 BUG

    Unity : 2020.3.37f1 Pipeline : BRP 備忘,便于日后索引 正常 手機顯卡芯片的浮點解析進度上的效果(其實不用手機上,PC 上將 uv * scale 一個巨大的值也會出現(xiàn)的) 異常 手機顯卡芯片的浮點解析進度上的效果(其實不用手機上,PC 上將 uv * scale 一個巨大的值也會出現(xiàn)的) 診斷發(fā)現(xiàn)是

    2024年02月11日
    瀏覽(27)
  • 完美解決!處理精度丟失問題點

    完美解決!處理精度丟失問題點

    目錄 1. 解決后端響應(yīng)數(shù)據(jù)給前端出現(xiàn)精度丟失問題 2. Freemark BigDecimal數(shù)據(jù)顯示精度丟失問題 3. 前端調(diào)用方法傳值精度丟失問題 解決方式一: 在項目中都是將注解標注在對應(yīng)字段上,在Json序列化的時候把Long自動轉(zhuǎn)為String。? 解決方式二: 全局配置?每個實體類的id字段都需要

    2024年02月15日
    瀏覽(101)
  • 前端計算數(shù)字精度丟失問題解決方法記錄

    在日常一些需求中,總會遇到一些需要前端進行手動計算的場景,那么這里需要優(yōu)先考慮的則是數(shù)字精度問題!具體請看下面截圖 如圖所示,在JavaScript進行浮點型數(shù)據(jù)計算當中,會出現(xiàn)計算結(jié)果“不正確”的現(xiàn)象。 我們知道浮點型數(shù)據(jù)類型主要有:單精度float、雙精度doub

    2024年02月05日
    瀏覽(96)
  • 如何解決前端傳遞數(shù)據(jù)給后端時精度丟失問題

    如何解決前端傳遞數(shù)據(jù)給后端時精度丟失問題

    有時候我們在進行修改操作時,發(fā)現(xiàn)修改既不報錯也不生效。我們進行排查后發(fā)現(xiàn)服務(wù)器端將數(shù)據(jù)返回給前端時沒有出錯,但是前端js將數(shù)據(jù)進行處理時卻出錯了,因為id是Long類型的,而js在處理后端返回給前端的Long類型數(shù)據(jù)時只能處理前16位,后3位進行了四舍五入操作,例

    2024年02月09日
    瀏覽(166)
  • 如何完美解決前端數(shù)字計算精度丟失與數(shù)字格式化問題?

    大家好,我是木瓜太香,做前端開發(fā)經(jīng)常會遇到數(shù)字計算精度丟失的問題,和數(shù)字格式化的麻煩問題,好不容易找到了可以解決這些問題的庫結(jié)果用起來不夠方便,例如 bignumber.js decimal.js 等編寫體驗不好,這篇文章來幫助你完美解決這些問題 接下來我們根據(jù)以下兩個問題展

    2024年02月16日
    瀏覽(27)
  • SpringBoot返回前端Long類型字段丟失精度問題及解決方案

    Java服務(wù)端返回Long整型數(shù)據(jù)給前端,JS會自動轉(zhuǎn)換為Number類型。而Long類型能表示的最大值為(),當數(shù)值超過JS中Number類型的最大值()時,就會丟失精度。 首先,引入依賴。 新建一個自定義大數(shù)據(jù)序列化類,如下: 新建Jackson配置類 本文針對Java服務(wù)端返回Long整型數(shù)據(jù)給前端時

    2024年03月22日
    瀏覽(305)
  • 2.6 浮點運算方法和浮點運算器

    2.6 浮點運算方法和浮點運算器

    ? 以下是一些具體的學習目標: 理解浮點數(shù)的基本概念和表示方法,包括符號位、指數(shù)和尾數(shù)。 學習浮點數(shù)的運算規(guī)則和舍入規(guī)則,包括加、減、乘、除、開方等。 了解浮點數(shù)的常見問題和誤差,例如舍入誤差、溢出、下溢等,并學會如何處理這些問題。 理解浮點運算器的

    2024年02月01日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包