最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解JavaScript中任意兩數(shù)加減的解決方案

 更新時間:2022年02月09日 10:27:13   作者:青山旁小溪邊  
JavaScript中一些浮點數(shù)相加減會計算錯誤,本文將為大家具體介紹一下JavaScript中解決任意兩數(shù)加減會出現(xiàn)錯誤的方案,需要的可以參考一下

寫在前面

本文是從初步解決到最終解決的思路,文章篇幅較長

雖然是一篇從0開始的文章,中間的思維跳躍可能比較大

代碼的解析都在文章的思路分析和注釋里,全文會幫助理解的幾個關(guān)鍵詞

1.Number.MAX_SAFE_INTEGER 和 Number.MIN_SAFE_INTEGER

2.15長度的字符串

3.padStart 和 padEnd

分析填坑思路

相信很多人都知道這是怎么回事吧

console.log( 0.1 + 0.2 === 0.3 )   // false
console.log( 0.3 - 0.2 === 0.1)   // false

不了解的出門右拐自己去查詢下,這里就不一一解釋了!

通過上面的例子可以知道,小數(shù)點的加減是存在問題的,那么有什么解決方式呢?

既然小數(shù)點加減有問題,那就先來整數(shù)進行加減吧,這個應(yīng)該就沒什么問題了小數(shù)點的加減自行百度解決,可以通過浮點計算,這里就不介紹了,那么整數(shù)的加減就一定沒有任何問題嗎?來看看下面的例子

const MAX = Number.MAX_SAFE_INTEGER;
console.log( MAX )  
// 9007199254740991
console.log( MAX + 2 ) 
// 9007199254740992

Number.MAX_SAFE_INTEGER是什么?

常量表示在 JavaScript 中最大的安全整數(shù)

所以,Number.MIN_SAFE_INTEGER就是最小安全系數(shù)

顧名思義,就是在JavaScript中加減法在這兩個范圍內(nèi)是穩(wěn)定的,是不是這樣就安全了?好像還是有點小問題:

console.log( 10**21 )
// 1e+21
console.log(9999999999999999)
// 9999999999999999
console.log(99999999999999999)
// 10000000000000000
console.log(999999999999999999999)
// 1e+21

從上面的結(jié)果來看,是不安全的

1.最后的結(jié)果是科學(xué)計數(shù)法

2.不知道具體的真實數(shù)據(jù)是多少

既然數(shù)字的顯示存在這樣的問題,把輸入結(jié)果和輸出結(jié)果都用字符串表示

console.log(`${10 ** 21}`)  
// '1e+21'
console.log('' + 10 ** 21)  
// '1e+21'
console.log((10 ** 21).toString())  
// '1e+21'

我們發(fā)現(xiàn)即使直接就轉(zhuǎn)換成字符串仍然會顯示為科學(xué)計數(shù)法,那么可以直接輸入字符串了,跳過轉(zhuǎn)成字符串的過程

解決整數(shù)加減的坑

先分析下可能性

1.輸入的數(shù)字在安全系數(shù)范圍內(nèi),且計算結(jié)果也在安全系數(shù)范圍內(nèi),這種直接輸出結(jié)果

2.不符合條件1(TODO)

    const MAX = Number.MAX_SAFE_INTEGER;
    const MIN = Number.MIN_SAFE_INTEGER;
    /**
     * @Description: 判斷輸入的數(shù)字是否在javascript的安全系數(shù)范圍內(nèi)
     * @param { number } 需要檢查的數(shù)字
     * @return { boolean }: 返回數(shù)字是否為安全的整數(shù)
     */
    function isSafeNumber(num) {
      // 即使 num 成了科學(xué)計數(shù)法也能正確的和 MAX, MIN 比較大小
      return MIN <= num && num <= MAX;
    }
    /**
     * @Description: 計算兩個數(shù)之和,返回計算結(jié)果
     * @param { String }: a 相加的第一個整數(shù)字符串
     * @param { String }: b 相加的第一個整數(shù)字符串
     * @return { string }: 返回計算結(jié)果
     */
    function IntAdd(a = "", b = "") {
      let result = "0";
      const intA = Number(a),
        intB = Number(b);
      if (intA === 0) return intB;
      if (intB === 0) return intA;
      if (
        isSafeNumber(intA) &&
        isSafeNumber(intB) &&
        isSafeNumber(intA + intB)
      ) {
        result = intA + intB;
      } else {
        result = IntCalc(a, b);
      }
      return result;
    }
    function IntCalc(a, b) {
      // TODO
    }
    function resClick() {
      const a = document.getElementById("ipt1").value;
      const b = document.getElementById("ipt2").value;
      const result = IntAdd(a, b);
      document.getElementById("res").innerText = result;
    }

如果不滿足上面條件的呢?

思路

獲取數(shù)字轉(zhuǎn)成字符串拆分成多個部分(數(shù)組),每一個部分的長度為 Number.MAX_SAFE_INTEGER 轉(zhuǎn)成字符串后的長度減一(15),長度不足15的用字符‘0’填充首部,再計算每個部分的結(jié)果后拼接在一起

同時考慮到正負號的問題,拆分后的計算需要帶上符號

長度減一的原因是接下來每部分的所有計算都是安全的,不需要在考慮是數(shù)字計算結(jié)果為安全的整數(shù)

同時每部分計算后的結(jié)果存在問題以及解決方案

注意:下面會使用15這個數(shù)字,15上面說過了,是Number.MAX_SAFE_INTEGER的長度減一

1.計算結(jié)果為0

那么這個部分賦值15個字符‘0’組成的字符串,即‘000000000000000’

2.計算結(jié)果為負數(shù)

那么向上一級數(shù)組借10的15次方,同時高位(下一級數(shù)組)減一,低位用10的15次方再加上這個負數(shù),做為這個部分的結(jié)果

3.計算結(jié)果為正數(shù),判斷長度:

如果長度超過15,那么去掉結(jié)果的第一位字符(因為進位,第一個字符一定是‘1’),同時高位(下一級數(shù)組)加一

如果長度沒有超過15,向首部補充0直到長度足夠15

如果長度等于15,直接添加到結(jié)果中

改造上面的代碼:

    const MAX = Number.MAX_SAFE_INTEGER;
    const MIN = Number.MIN_SAFE_INTEGER;
    const intLen = `${MAX}`.length - 1;
    /**
     * @Description: 判斷輸入的數(shù)字是否在javascript的安全系數(shù)范圍內(nèi)
     * @param { number } 需要檢查的數(shù)字
     * @return { boolean }: 返回數(shù)字是否為安全的整數(shù)
     */
    function isSafeNumber(num) {
      // 即使 num 成了科學(xué)計數(shù)法也能正確的和 MAX, MIN 比較大小
      return MIN <= num && num <= MAX;
    }
    /**
     * @Description: 計算兩個數(shù)之和,返回計算結(jié)果
     * @param { String }: a 相加的第一個整數(shù)字符串
     * @param { String }: b 相加的第一個整數(shù)字符串
     * @return { string }: 返回計算結(jié)果
     */
    function IntAdd(a = "", b = "") {
      const statusObj = checkNumber(a, b);
      if (!statusObj.status) {
        return statusObj.data;
      } else {
        const tagA = Number(a) < 0,
          tagB = Number(b) < 0;
        const strA = `${a}`,
          strB = `$`;
        const lenA = tagA ? strA.length - 1 : strA.length;
        const lenB = tagB ? strB.length - 1 : strB.length;
        const maxLen = Math.max(lenA, lenB);
        const padLen = Math.ceil(maxLen / intLen) * intLen; // 即為會用到的整個數(shù)組長度
        const newA = tagA
          ? `-${strA.slice(1).padStart(padLen, "0")}`
          : strA.padStart(padLen, "0");
        const newB = tagB
          ? `-${strB.slice(1).padStart(padLen, "0")}`
          : strB.padStart(padLen, "0");
        let result = IntCalc(newA, newB);
        // 去掉正負數(shù)前面無意義的字符 ‘0'
        const numberResult = Number(result);
        if (numberResult > 0) {
          while (result[0] === "0") {
            result = result.slice(1);
          }
        } else if (numberResult < 0) {
          while (result[1] === "0") {
            result = "-" + result.slice(2);
          }
        } else {
          result = "0";
        }
        return result;
      }
    }
    function IntCalc(a, b) {
      let result = "0";
      const intA = Number(a),
        intB = Number(b);
      // 判斷是否為安全數(shù),不為安全數(shù)的操作進入復(fù)雜計算模式
      if (
        isSafeNumber(intA) &&
        isSafeNumber(intB) &&
        isSafeNumber(intA + intB)
      ) {
        result = `${intA + intB}`;
      } else {
        const sliceA = a.slice(1),
          sliceB = b.slice(1);
        if (a[0] === "-" && b[0] === "-") {
          // 兩個數(shù)都為負數(shù),取反后計算,結(jié)果再取反
          result = "-" + calc(sliceA, sliceB, true);
        } else if (a[0] === "-") {
          // 第一個數(shù)為負數(shù),第二個數(shù)為正數(shù)的情況
          const newV = compareNumber(sliceA, b);
          if (newV === 1) {
            // 由于 a 的絕對值比 b 大,為了確保返回結(jié)果為正數(shù),a的絕對值作為第一個參數(shù)
            result = "-" + calc(sliceA, b, false);
          } else if (newV === -1) {
            // 道理同上
            result = calc(b, sliceA, false);
          }
        } else if (b[0] === "-") {
          // 第一個數(shù)為正數(shù),第二個數(shù)為負數(shù)的情況
          const newV = compareNumber(sliceB, a);
          if (newV === 1) {
            // 由于 b 的絕對值比 a 大,為了確保返回結(jié)果為正數(shù),b的絕對值作為第一個參數(shù)
            result = "-" + calc(sliceB, a, false);
          } else if (newV === -1) {
            // 道理同上
            result = calc(a, sliceB, false);
          }
        } else {
          // 兩個數(shù)都為正數(shù),直接計算
          result = calc(a, b, true);
        }
      }
      return result;
    }
    /**
     * @Description: 比較兩個整數(shù)字符串是否正確
     * @param { string }: 比較的第一個整數(shù)字符串
     * @param { string }: 比較的第一個整數(shù)字符串
     * @return { object }: 返回是否要退出函數(shù)的狀態(tài)和退出函數(shù)返回的數(shù)據(jù)
     */
    function checkNumber(a, b) {
      const obj = {
        status: true,
        data: null
      };
      const typeA = typeof a,
        typeB = typeof b;
      const allowTypes = ["number", "string"];
      if (!allowTypes.includes(typeA) || !allowTypes.includes(typeB)) {
        console.error("參數(shù)中存在非法的數(shù)據(jù),數(shù)據(jù)類型只支持 number 和 string");
        obj.status = false;
        obj.data = false;
      }
      if (Number.isNaN(a) || Number.isNaN(b)) {
        console.error("參數(shù)中不應(yīng)該存在 NaN");
        obj.status = false;
        obj.data = false;
      }
      const intA = Number(a),
        intB = Number(b);
      if (intA === 0) {
        obj.status = false;
        obj.data = b;
      }
      if (intB === 0) {
        obj.status = false;
        obj.data = a;
      }
      const inf = [Infinity, -Infinity];
      if (inf.includes(intA) || inf.includes(intB)) {
        console.error("參數(shù)中存在Infinity或-Infinity");
        obj.status = false;
        obj.data = false;
      }
      return obj;
    }
    /**
     * @Description: 比較兩個整數(shù)字符串正負
     * @param { string } a 比較的第一個整數(shù)字符串
     * @param { string } b 比較的第二個整數(shù)字符串
     * @return { boolean } 返回第一個參數(shù)與第二個參數(shù)的比較
     */
    function compareNumber(a, b) {
      if (a === b) return 0;
      if (a.length > b.length) {
        return 1;
      } else if (a.length < b.length) {
        return -1;
      } else {
        for (let i = 0; i < a.length; i++) {
          if (a[i] > b[i]) {
            return 1;
          } else if (a[i] < b[i]) {
            return -1;
          }
        }
      }
    }

    /**
     * @Description: 相加的結(jié)果
     * @param { string } a 相加的第一個整數(shù)字符串
     * @param { string } b 相加的第二個整數(shù)字符串
     * @param { string } type 兩個參數(shù)是 相加(true) 還是相減(false)
     * @return { string } 返回相加的結(jié)果
     */
    function calc(a, b, type = true) {
      const arr = []; // 保存每個部分計算結(jié)果的數(shù)組
      for (let i = 0; i < a.length; i += intLen) {
        // 每部分長度 15 的裁取字符串
        const strA = a.slice(i, i + intLen);
        const strB = b.slice(i, i + intLen);
        const newV = Number(strA) + Number(strB) * (type ? 1 : -1); // 每部分的計算結(jié)果,暫時不處理
        arr.push(`${newV}`);
      }
      let num = ""; // 連接每個部分的字符串
      for (let i = arr.length - 1; i >= 0; i--) {
        if (arr[i] > 0) {
          // 每部分結(jié)果大于 0 的處理方案
          const str = `${arr[i]}`;
          if (str.length < intLen) {
            // 長度不足 15 的首部補充字符‘0'
            num = str.padStart(intLen, "0") + num;
          } else if (str.length > intLen) {
            // 長度超過 15 的扔掉第一位,下一部分進位加一
            num = str.slice(1) + num;
            if (i >= 1 && str[0] !== "0") arr[i - 1]++;
            else num = "1" + num;
          } else {
            // 長度等于 15 的直接計算
            num = str + num;
          }
        } else if (arr[i] < 0) {
          // 每部分結(jié)果小于 0 的處理方案,借位 10的15次方計算,結(jié)果恒為正數(shù),首部填充字符‘0'到15位
          const newV = `${10 ** intLen + Number(arr[i])}`;
          num = newV.padStart(intLen, "0") + num;
          if (i >= 1) arr[i - 1]--;
        } else {
          // 每部分結(jié)果等于 0 的處理方案,連續(xù)15個字符‘0'
          num = "0".padStart(intLen, "0") + num;
        }
      }
      return num;
    }

測試結(jié)果:

全部代碼請點擊 這里

console.log(MAX)  // 9007199254740991
intAdd(MAX, '2')  // '9007199254740993'
intAdd(MAX, '10000000000000000')  // '19007199254740991'
// 下面測試10的二十一次方的數(shù)據(jù) 1000000000000000000000
intAdd(MAX, '1000000000000000000000')  // '1000009007199254740991'
intAdd(MAX, `-${10 ** 16}`)  // '-992800745259009'
// 仍然存在一個問題,就是不要使用計算中的字符串,如下
intAdd(MAX, `${10 ** 21}`)  // '10.0000000071992548e+21'
intAdd(MAX, `-${10 ** 21}`)  // '0'

轉(zhuǎn)換科學(xué)計算

當(dāng)然考慮到由于一般計算不會使用大數(shù),書寫字符串相加確實感覺怪怪的,可以在函數(shù)內(nèi)加入判斷,是科學(xué)計數(shù)法的提示并轉(zhuǎn)換為10進制數(shù),進行代碼改進:

/**
 * @Description: 計算兩個數(shù)之和,返回計算結(jié)果
 * @param { String }: a 相加的第一個整數(shù)字符串
 * @param { String }: b 相加的第一個整數(shù)字符串
 * @return { string }: 返回計算結(jié)果
 */
function intAdd(a = "", b = "") {
  const statusObj = checkNumber(a, b);
  if (!statusObj.status) {
    return statusObj.data;
  } else {
    let newA, newB, maxLen;
    const tagA = Number(a) < 0,
      tagB = Number(b) < 0;
    let strA = `${a}`,
      strB = `$`;
    const reg = /^\-?(\d+)(\.\d+)?e\+(\d+)$/;
    if (reg.test(a) || reg.test(b)) {
      console.warn(
        "由于存在科學(xué)計數(shù)法,計算結(jié)果不一定準(zhǔn)確,請轉(zhuǎn)化成字符串后計算"
      );
      strA = strA.replace(reg, function(...rest) {
        const str = rest[2] ? rest[1] + rest[2].slice(1) : rest[1];
        return str.padEnd(Number(rest[3]) + 1, "0");
      });
      strB = strB.replace(reg, function(...rest) {
        const str = rest[2] ? rest[1] + rest[2].slice(1) : rest[1];
        return str.padEnd(Number(rest[3]) + 1, "0");
      });
      maxLen = Math.max(a.length, b.length);
    } else {
      const lenA = tagA ? strA.length - 1 : strA.length;
      const lenB = tagB ? strB.length - 1 : strB.length;
      maxLen = Math.max(lenA, lenB);
    }
    const padLen = Math.ceil(maxLen / intLen) * intLen; // 即為會用到的整個數(shù)組長度
    newA = tagA
      ? `-${strA.slice(1).padStart(padLen, "0")}`
      : strA.padStart(padLen, "0");
    newB = tagB
      ? `-${strB.slice(1).padStart(padLen, "0")}`
      : strB.padStart(padLen, "0");
    let result = intCalc(newA, newB);
    // 去掉正負數(shù)前面無意義的字符 ‘0'
    const numberResult = Number(result);
    if (numberResult > 0) {
      while (result[0] === "0") {
        result = result.slice(1);
      }
    } else if (numberResult < 0) {
      while (result[1] === "0") {
        result = "-" + result.slice(2);
      }
    } else {
      result = "0";
    }
    console.log(result);
    return result;
  }
}

解決整數(shù)減法的坑

加法和減法同理,只需要把第二個參數(shù)取反后利用加法運算就可以了,由于之前已經(jīng)提取了模板,可以直接定義減法函數(shù)

/**
 * @Description: 整數(shù)減法函數(shù)入口
 * @param { String }: a 減法的第一個整數(shù)字符串
 * @param { String }: b 減法的第一個整數(shù)字符串
 * @return { string }: 返回計算結(jié)果
 */
function intSub(a = "0", b = "0") {
  const newA = `${a}`;
  const newB = Number(b) > 0 ? `-$` : `$`.slice(1);
  const result = intAdd(newA, newB);
  return result;
}

測試結(jié)果

全部代碼請點擊 這里

intSub('9037499254750994', '-9007299251310995')
// 18044798506061989

解決小數(shù)加法的坑

文章開頭說了,小數(shù)加減,可以通過浮點進行計算,但是這里既然完成了整數(shù)的加減,那么能不能利用整數(shù)的加減原理來解決小數(shù)的加減計算呢?

  • 整數(shù)加法代碼中經(jīng)常出現(xiàn) padStart 這個向前補齊的函數(shù),因為在整數(shù)前加字符‘0’的對本身沒有影響。
  • 小數(shù)也有這個原理,往尾部補‘0’同樣對小數(shù)沒有影響,然后再補齊后的數(shù)通過整數(shù)加減來計算。

首先來看下小數(shù)的加法計算實現(xiàn)

/**
 * @Description: 小數(shù)加法函數(shù)入口
 * @param { String }: a 相加的第一個整數(shù)字符串
 * @param { String }: b 相加的第一個整數(shù)字符串
 * @return { string }: 返回計算結(jié)果
 */
function floatAdd(a = "0", b = "0") {
  const statusObj = checkNumber(a, b);
  if (!statusObj.status) {
    return statusObj.data;
  } else {
    const strA = `${a}`.split("."),
      strB = `$`.split(".");
    let newA = strA[1],
      newB = strB[1];
    const maxLen = Math.max(newA.length, newB.length);
    const floatLen = Math.ceil(maxLen / intLen) * intLen;
    newA = newA.padEnd(floatLen, "0");
    newB = newB.padEnd(floatLen, "0");
    newA = strA[0][0] === "-" ? `-${newA}` : newA;
    newB = strB[0][0] === "-" ? `-${newB}` : newB;
    let result = intCalc(newA, newB);
    let tag = true,
      numResult = Number(result);
    // 去掉正負數(shù)后面無意義的字符 ‘0'
    if (numResult !== 0) {
      if (numResult < 0) {
        result = result.slice(1);
        tag = false;
      }
      result =
        result.length === floatLen ? `0.${result}` : `1.${result.slice(1)}`;
      result = tag ? result : `-${result}`;
      let index = result.length - 1;
      while (result[index] === "0") {
        result = result.slice(0, -1);
        index--;
      }
    } else {
      result = "0";
    }
    console.log(result);
    return result;
  }
}

測試結(jié)果

floatAdd('0.9037499254750994', '-0.9007299251310995')
// 0.0030200003439999

解決小數(shù)減法的坑

與整數(shù)減法的原理相同,可以直接定義減法函數(shù)

/**
 * @Description: 小數(shù)減法函數(shù)入口
 * @param { String }: a 相減的第一個整數(shù)字符串
 * @param { String }: b 相減的第一個整數(shù)字符串
 * @return { string }: 返回計算結(jié)果
 */
function floatSub(a = '0', b = '0') {
  const newA = `${a}`
  const newB = Number(b) > 0 ? `-$`: `${b.slice(1)}`
  const result = floatAdd(newA, newB)
  return result
}

測試結(jié)果

全部代碼請點擊 這里

floatSub('0.9037499254750994', '-0.9007299251310995')
// 1.8044798506061989

解決整數(shù)加小數(shù)的通用問題

其實在實際開發(fā)過程中,并不是整數(shù)相加減,小數(shù)相加減,都有可能出現(xiàn),所以還要考慮整數(shù)與小數(shù)之間的加減計算

這里的解決思路仍然是往前補0和往后補0

把整數(shù)和小數(shù)都補充完整后,合在一起進行整數(shù)相加

最后根據(jù)之前保存的整數(shù)的長度,插入小數(shù)點

剩下的就是把無意義的0排除掉,輸出結(jié)果

/**
 * @Description: 計算兩個數(shù)之差,返回計算結(jié)果
 * @param { String }: a 相減的第一個整數(shù)字符串
 * @param { String }: b 相減的第一個整數(shù)字符串
 * @return { string }: 返回計算結(jié)果
 */
function allSub(a = "0", b = "0") {
  const newA = `${a}`;
  const newB = Number(b) > 0 ? `-$` : `$`.slice(1);
  const result = allAdd(newA, newB);
  return result;
}
/**
 * @Description: 計算兩個數(shù)之和,返回計算結(jié)果
 * @param { String }: a 相加的第一個整數(shù)字符串
 * @param { String }: b 相加的第一個整數(shù)字符串
 * @return { string }: 返回計算結(jié)果
 */
function allAdd(a = "0", b = "0") {
  const statusObj = checkNumber(a, b);
  if (!statusObj.status) {
    return statusObj.data;
  } else {
    const strA = `${a}`.split("."),
      strB = `$`.split(".");
    let intAs = strA[0],
      floatA = strA.length === 1 ? "0" : strA[1];
    let intBs = strB[0],
      floatB = strB.length === 1 ? "0" : strB[1];
    // 可能存在純整數(shù) 或者純小數(shù) 0.xxxxxxx
    const tagA = intAs > 0 || !intAs[0] === '-' || intAs[0] === '0',
      tagB = intBs > 0 || !intBs[0] === '-' || intBs[0] === '0';
    const maxIntLen = Math.max(intAs.length, intBs.length);
    const arrIntLen = Math.ceil(maxIntLen / intLen) * intLen;
    const maxFloatLen = Math.max(floatA.length, floatB.length);
    const arrFloatLen = Math.ceil(maxFloatLen / intLen) * intLen;
    intAs = tagA
      ? intAs.padStart(arrIntLen, "0")
      : intAs.slice(1).padStart(arrIntLen, "0");
    intBs = tagB
      ? intBs.padStart(arrIntLen, "0")
      : intBs.slice(1).padStart(arrIntLen, "0");
    let newA =
      floatA === "0"
        ? intAs + "0".padEnd(arrFloatLen, "0")
        : intAs + floatA.padEnd(arrFloatLen, "0");
    let newB =
      floatB === "0"
        ? intBs + "0".padEnd(arrFloatLen, "0")
        : intBs + floatB.padEnd(arrFloatLen, "0");
    newA = tagA ? newA : `-${newA}`;
    newB = tagB ? newB : `-${newB}`;
    let result = intCalc(newA, newB);
    const numResult = Number(result);
    if (result.length > arrIntLen) {
      result = result.slice(0, -arrFloatLen) + "." + result.slice(arrFloatLen);
    }
    // 去掉正負數(shù)前面后面無意義的字符 ‘0'
    if (numResult !== 0) {
      if (numResult > 0) {
        while (result[0] === "0") {
          result = result.slice(1);
        }
      } else if (numResult < 0) {
        while (result[1] === "0") {
          result = "-" + result.slice(2);
        }
        result = result.slice(1);
        tag = false;
      }
      let index = result.length - 1;
      while (result[index] === "0") {
        result = result.slice(0, -1);
        index--;
      }
    } else {
      result = "0";
    }
    if (result[result.length - 1] === ".") {
      result = result.slice(0, -1);
    }
    if (result[0] === ".") {
      result = "0" + result;
    }
    console.log(result);
    return result;
  }
}

測試結(jié)果

全部代碼請點擊 這里

allAdd("9037499254750994", "0.9007299251310995");
// 9037499254750994.9007299251310995
allSub("9037499254750994", "-0.9007299251310995");
// 9037499254750994.9007299251310995
allAdd('9037499254750994.9037499254750994', '-9007299251310995.9007299251310995');
// 30200003439999.0030200003439999
allSub('9037499254750994.9037499254750994', '9007299251310995.9007299251310995');
// 30200003439999.0030200003439999

總結(jié)

Number.MAX_SAFE_INTEGER 和 Number.MIN_SAFE_INTEGER 之間的計算才是可信任的

小數(shù)加減的浮點精度問題轉(zhuǎn)移到整數(shù)來解決

超大的數(shù)加減的時候,分區(qū)計算(理由是第1點)

拆分成每部分15長度的字符串(理由是Number.MAX_SAFE_INTEGER的長度為16,無論如何加減都是滿足第一點的,這樣就不需要去注意加減的安全性問題了)

科學(xué)計數(shù)法的問題,匹配是否為科學(xué)計數(shù)法的數(shù),然后轉(zhuǎn)換成十進制,同時提出警告,因為科學(xué)計數(shù)法的數(shù)存在誤差,計算會存在不準(zhǔn)確性

以上就是詳解JavaScript中任意兩數(shù)加減的解決方案的詳細內(nèi)容,更多關(guān)于JavaScript數(shù)字加減的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JS操作iframe里的dom(實例講解)

    JS操作iframe里的dom(實例講解)

    本篇主要是對JS操作iframe里的dom進行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2014-01-01
  • 微信小程序wx.getUserInfo授權(quán)獲取用戶信息(頭像、昵稱)的實現(xiàn)

    微信小程序wx.getUserInfo授權(quán)獲取用戶信息(頭像、昵稱)的實現(xiàn)

    這篇文章主要介紹了微信小程序wx.getUserInfo授權(quán)獲取用戶信息(頭像、昵稱)的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • JavaScript回調(diào)(callback)函數(shù)概念自我理解及示例

    JavaScript回調(diào)(callback)函數(shù)概念自我理解及示例

    此文適合JavaScript入門級選手閱讀,在JavaScript里什么叫Callback“回調(diào)函數(shù)”,把方法b當(dāng)做一個參數(shù)傳遞個方法a,當(dāng)方法a執(zhí)行完后執(zhí)行另外一個指定函數(shù)(這里是b函數(shù)),感興趣的朋友可以了解下哈
    2013-07-07
  • JavaScript基于對象去除數(shù)組重復(fù)項的方法

    JavaScript基于對象去除數(shù)組重復(fù)項的方法

    這篇文章主要介紹了JavaScript基于對象去除數(shù)組重復(fù)項的方法,結(jié)合實例形式分析了javascript數(shù)組去重的操作步驟與具體實現(xiàn)技巧,需要的朋友可以參考下
    2016-10-10
  • uniapp實現(xiàn)可滑動選項卡

    uniapp實現(xiàn)可滑動選項卡

    這篇文章主要為大家詳細介紹了uniapp實現(xiàn)可滑動選項卡,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-10-10
  • JS實現(xiàn)圖片局部放大或縮小的方法

    JS實現(xiàn)圖片局部放大或縮小的方法

    這篇文章主要介紹了JS實現(xiàn)圖片局部放大或縮小的方法,涉及javascript事件響應(yīng)及頁面元素動態(tài)操作相關(guān)技巧,需要的朋友可以參考下
    2016-08-08
  • 深入剖析javascript中的exec與match方法

    深入剖析javascript中的exec與match方法

    下面小編就為大家?guī)硪黄钊肫饰鰆avascript中的exec與match方法。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-05-05
  • javascript的var與let,const之間的區(qū)別詳解

    javascript的var與let,const之間的區(qū)別詳解

    這篇文章主要為大家介紹了?javascript的var與let,const之間的區(qū)別,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • 瀏覽器頁面區(qū)域大小的js獲取方法

    瀏覽器頁面區(qū)域大小的js獲取方法

    瀏覽器頁面的區(qū)域大小如何獲取,在本有個不錯的示例,感興趣的朋友可以參考下,希望對大家有所幫助
    2013-09-09
  • js自定義trim函數(shù)實現(xiàn)刪除兩端空格功能

    js自定義trim函數(shù)實現(xiàn)刪除兩端空格功能

    這篇文章主要介紹了js自定義trim函數(shù)實現(xiàn)刪除兩端空格功能,結(jié)合實例形式分析了javascript基于正則替換實現(xiàn)類似trim函數(shù)刪除字符串兩端空格的相關(guān)操作技巧,并附帶jQuery類似功能函數(shù)使用方法,需要的朋友可以參考下
    2018-02-02

最新評論

苏州市| 湖口县| 喀什市| 亳州市| 开江县| 抚州市| 武城县| 喀喇沁旗| 永泰县| 南溪县| 大悟县| 郸城县| 武陟县| 白城市| 博乐市| 孟州市| 清苑县| 文山县| 缙云县| 延安市| 西乌珠穆沁旗| 藁城市| 原阳县| 马尔康县| 桦南县| 社旗县| 北海市| 马关县| 景泰县| 涞源县| 文成县| 永定县| 延津县| 涟源市| 东方市| 潢川县| 枣庄市| 崇仁县| 本溪市| 类乌齐县| 沙雅县|