解決浮運(yùn)算問題

/*js浮點(diǎn)數(shù)運(yùn)算問題解決辦法
   @params type: 1乘法奈懒,2除法 3減法,4加法
   @params arg1 arg2 按照表達(dá)式順序來
   */

  floatCalculation(arg1, arg2, type) {
    if (type == 1) {
      let m = 0,
        s1 = arg1.toString(),
        s2 = arg2.toString();
      try {
        m += s1.split(".")[1].length
      } catch (e) {
        console.log(e)
      }
      try {
        m += s2.split(".")[1].length
      } catch (e) {
        console.log(e)
      }
      return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
    } else if (type == 2) {
      let t1 = 0,
        t2 = 0,
        r1, r2;
      try {
        t1 = arg1.toString().split(".")[1].length
      } catch (e) {
        console.log(e)
      }
      try {
        t2 = arg2.toString().split(".")[1].length
      } catch (e) {
        console.log(e)
      }
      r1 = Number(arg1.toString().replace(".", ""));
      r2 = Number(arg2.toString().replace(".", ""));
      return (r1 / r2) * Math.pow(10, t2 - t1);
    } else if (type == 3) {
      let r1, r2, m, n;
      try {
        r1 = arg1.toString().split(".")[1].length
      } catch (e) {
        r1 = 0
      }
      try {
        r2 = arg2.toString().split(".")[1].length
      } catch (e) {
        r2 = 0
      }
      m = Math.pow(10, Math.max(r1, r2));
      //last modify by deeka
      //動(dòng)態(tài)控制精度長度
      n = (r1 >= r2) ? r1 : r2;
      return ((arg2 * m - arg1 * m) / m).toFixed(n);
    } else if (type == 4) {
      let r1, r2, m;
      try {
        r1 = arg1.toString().split(".")[1].length
      } catch (e) {
        r1 = 0
      }
      try {
        r2 = arg2.toString().split(".")[1].length
      } catch (e) {
        r2 = 0
      }
      m = Math.pow(10, Math.max(r1, r2));
      return (arg1 * m + arg2 * m) / m;
    }
  }

另外一遍文章里面原文地址

/**
 * @file 解決浮動(dòng)運(yùn)算問題宪巨,避免小數(shù)點(diǎn)后產(chǎn)生多位數(shù)和計(jì)算精度損失磷杏。
 * 問題示例:2.3 + 2.4 = 4.699999999999999,1.0 - 0.9 = 0.09999999999999998
 */

/**
 * 把錯(cuò)誤的數(shù)據(jù)轉(zhuǎn)正
 * strip(0.09999999999999998)=0.1
 */
function strip(num, precision = 12) {
  return +parseFloat(num.toPrecision(precision));
}

/**
 * Return digits length of a number
 * @param {*number} num Input number
 */
function digitLength(num) {
  // Get digit length of e
  const eSplit = num.toString().split(/[eE]/);
  const len = (eSplit[0].split('.')[1] || '').length - (+(eSplit[1] || 0));
  return len > 0 ? len : 0;
}

/**
 * 把小數(shù)轉(zhuǎn)成整數(shù)捏卓,支持科學(xué)計(jì)數(shù)法极祸。如果是小數(shù)則放大成整數(shù)
 * @param {*number} num 輸入數(shù)
 */
function float2Fixed(num) {
  if (num.toString().indexOf('e') === -1) {
    return Number(num.toString().replace('.', ''));
  }
  const dLen = digitLength(num);
  return dLen > 0 ? num * Math.pow(10, dLen) : num;
}

/**
 * 檢測(cè)數(shù)字是否越界,如果越界給出提示
 * @param {*number} num 輸入數(shù)
 */
function checkBoundary(num) {
  if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
    console.warn(`${num} is beyond boundary when transfer to integer, the results may not be accurate`);
  }
}

/**
 * 精確乘法
 */
function times(num1, num2) {
  const num1Changed = float2Fixed(num1);
  const num2Changed = float2Fixed(num2);
  const baseNum = digitLength(num1) + digitLength(num2);
  const leftValue = num1Changed * num2Changed;

  checkBoundary(leftValue);

  return leftValue / Math.pow(10, baseNum);
}

/**
 * 精確加法
 */
function plus(num1, num2) {
  const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
  return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
}

/**
 * 精確減法
 */
function minus(num1, num2) {
  const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
  return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
}

/**
 * 精確除法
 */
function divide(num1, num2) {
  const num1Changed = float2Fixed(num1);
  const num2Changed = float2Fixed(num2);
  checkBoundary(num1Changed);
  checkBoundary(num2Changed);
  return times((num1Changed / num2Changed), Math.pow(10, digitLength(num2) - digitLength(num1)));
}

/**
 * 四舍五入
 */
function round(num, ratio) {
  const base = Math.pow(10, ratio);
  return divide(Math.round(times(num, base)), base);
}

export { strip, plus, minus, times, divide, round, digitLength, float2Fixed };
export default { strip, plus, minus, times, divide, round, digitLength, float2Fixed };
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末怠晴,一起剝皮案震驚了整個(gè)濱河市遥金,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蒜田,老刑警劉巖稿械,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異冲粤,居然都是意外死亡溜哮,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門色解,熙熙樓的掌柜王于貴愁眉苦臉地迎上來茂嗓,“玉大人,你說我怎么就攤上這事科阎∈鑫” “怎么了?”我有些...
    開封第一講書人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵锣笨,是天一觀的道長蝌矛。 經(jīng)常有香客問我,道長错英,這世上最難降的妖魔是什么入撒? 我笑而不...
    開封第一講書人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮椭岩,結(jié)果婚禮上茅逮,老公的妹妹穿的比我還像新娘。我一直安慰自己判哥,他們只是感情好献雅,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著塌计,像睡著了一般挺身。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上锌仅,一...
    開封第一講書人閱讀 52,682評(píng)論 1 312
  • 那天章钾,我揣著相機(jī)與錄音墙贱,去河邊找鬼。 笑死贱傀,一個(gè)胖子當(dāng)著我的面吹牛惨撇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播窍箍,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼串纺,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了椰棘?” 一聲冷哼從身側(cè)響起纺棺,我...
    開封第一講書人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎邪狞,沒想到半個(gè)月后祷蝌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡帆卓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年巨朦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片剑令。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡糊啡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出吁津,到底是詐尸還是另有隱情棚蓄,我是刑警寧澤,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布碍脏,位于F島的核電站梭依,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏典尾。R本人自食惡果不足惜役拴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望钾埂。 院中可真熱鬧河闰,春花似錦、人聲如沸勃教。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽故源。三九已至,卻和暖如春汞贸,著一層夾襖步出監(jiān)牢的瞬間绳军,已是汗流浹背印机。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留门驾,地道東北人射赛。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像奶是,于是被迫代替她去往敵國和親楣责。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容