Heim  >  Artikel  >  Web-Frontend  >  Detaillierte Erläuterung der Verarbeitung von JS-Gleitkommazahlenoperationen

Detaillierte Erläuterung der Verarbeitung von JS-Gleitkommazahlenoperationen

高洛峰
高洛峰Original
2016-12-05 09:41:271487Durchsuche

1. Problembeschreibung

Ich arbeite kürzlich an einem Projekt. Es werden einige Fehler bei JS-Gleitkommazahlenoperationen festgestellt :

0.1+0.2 == 0.30000000000000004
  
0.1 + 0.7 == 0.7999999999999999
  
7*0.8 == 5.6000000000000005
  
5.6/7 == 0.7999999999999999

2. Lösung

Nach dem JS-Betrieb tritt ein sehr kleiner Fehler auf. Der Hauptgrund ist, dass der Fokus von JS liegt ist nicht im Betrieb, aber manchmal muss es in Projekten verwendet werden. Es gibt zwei Lösungen

Eine Lösung 1:

Das Operationsergebnis behält 2-3 Dezimalstellen bei Die Front-End-Schnittstelle erfordert im Allgemeinen weniger Vorgänge. Die Genauigkeitsanforderungen sind nicht zu hoch. Nehmen Sie also einfach 2 Dezimalstellen.

B. Option 2:

Konvertieren Sie die Anzahl der Dezimalstellen in Ganzzahloperationen. Zum Beispiel:

0.1+0.2 =》 (1+2)/10 == 0.3
  
0.1 + 0.7 =》 (1+7)/10 == 0.8
  
7*0.8 == (7*8)/10 == 5.6
  
5.6/7 == (56/7)/10 == 0.1

Damit wir eine Öffentlichkeit extrahieren können Methode. In der folgenden JSMath-Bibliothek schreibt JSMath beispielsweise Addition, Subtraktion, Multiplikation und Division neu. Es konvertiert zunächst die Parameter in Ganzzahlen und führt dann die Operation (Parameter 2) von JSMath aus 1 und Parameter 2 sind die Operationen. Nach der Berechnung erhalten Sie den Wert über die Value-Eigenschaft.

B1. Grundoperationen
(function() {
  
  var JSMath = function() {
    return this;
  }
  
  JSMath.prototype.from = function(value) {
  
    // 支持JSMath参数传递主要是用于嵌套的调用
    if ((typeof(value) == 'object') && (value.value != undefined)) {
      this.value = value.value;
    } else {
      this.value = value;
    }
    return this;
  }
  
  // 加法
  JSMath.prototype.add = function(value) {
    var thisValueString = this.value.toString();
    var valueString = value.toString();
    var timesCount1 = 0;
    var timesCount2 = 0;
    if (thisValueString.indexOf('.') > 0) {
      timesCount1 = thisValueString.split('.')[1].length;
    }
    if (valueString.indexOf('.') > 0) {
      timesCount2 = valueString.split('.')[1].length;
    }
    var maxtimeCount = timesCount1 > timesCount2 ? timesCount1 : timesCount2;
    this.value = (Math.pow(10, maxtimeCount) * this.value + Math.pow(10, maxtimeCount) * value) / Math.pow(10, maxtimeCount);
    return this;
  }
   
 // 减法
  JSMath.prototype.sub = function(value) {
    var thisValueString = this.value.toString();
    var valueString = value.toString();
    var timesCount1 = 0;
    var timesCount2 = 0;
    if (thisValueString.indexOf('.') > 0) {
      timesCount1 = thisValueString.split('.')[1].length;
    }
    if (valueString.indexOf('.') > 0) {
      timesCount2 = valueString.split('.')[1].length;
    }
    var maxtimeCount = timesCount1 > timesCount2 ? timesCount1 : timesCount2;
    this.value = (Math.pow(10, maxtimeCount) * this.value - Math.pow(10, maxtimeCount) * value) / Math.pow(10, maxtimeCount);
    return this;
  }
  
  // 除法  
  JSMath.prototype.div = function(value) {
    var thisValueString = this.value.toString();
    var valueString = value.toString();
    var timesCount1 = 0;
    var timesCount2 = 0;
    if (thisValueString.indexOf('.') > 0) {
      timesCount1 = thisValueString.split('.')[1].length;
    }
    if (valueString.indexOf('.') > 0) {
      timesCount2 = valueString.split('.')[1].length;
    }
    var maxtimeCount = timesCount1 > timesCount2 ? timesCount1 : timesCount2;
    this.value = ((Math.pow(10, maxtimeCount) * this.value) / (Math.pow(10, maxtimeCount) * value));
    return this;
  }
  
  // 乘法
  JSMath.prototype.times = function(value) {
  
    var thisValueString = this.value.toString();
    var valueString = value.toString();
    var timesCount1 = 0;
    var timesCount2 = 0;
    if (thisValueString.indexOf('.') > 0) {
      timesCount1 = thisValueString.split('.')[1].length;
    }
    if (valueString.indexOf('.') > 0) {
      timesCount2 = valueString.split('.')[1].length;
    }
    var maxtimeCount = timesCount1 > timesCount2 ? timesCount1 : timesCount2;
    this.value = (Math.pow(10, maxtimeCount) * this.value * Math.pow(10, maxtimeCount) * value) / Math.pow(10, maxtimeCount * 2);
    return this;
  }
  
  if (window.JSMath == undefined) {
    window.JSMath = function(value) {
      var result = new JSMath();
      result.from(value);
      return result;
    }
  }
})()

B2. Operationen mit mehreren Objekten
  0.1+0.2
=> JSMath(0.1).add(0.2).value == 0.3
  
7+0.8
=> JSMath(7).times(0.8).value == 5.6
  
5.6/7
=> JSMath(5.6).div(7).value = 0.8

3. Kleine Zusammenfassung
  0.05 + 0.05 + 0.2
=> JSMath(JSMath(0.05).add(0.05)).add(0.2).value == 0.3
  
(5+0.6)/7
=> JSMath(JSMath(5).add(0.6)).div(7).value == 0.8

Einige Lösungen, die mir vorerst bekannt sind. Es ist nicht klar, ob es eine zuverlässigere Open-Source-Bibliothek eines Drittanbieters zur Lösung dieses Problems gibt.

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn