Lösung für das Problem ungenauer JS-Zahlen

Lösung für das Problem ungenauer JS-Zahlen

Die verständlichste Erklärung des Genauigkeitsproblems

Beispielsweise ist die Zahl 1÷3=0,33333333... Jeder weiß, dass sich 3 unendlich oft wiederholt, und die Mathematik kann das ausdrücken, aber der Computer muss sie speichern, damit sie beim nächsten Mal abgerufen und verwendet werden kann. Aber 0,333333... diese Zahl wiederholt sich unendlich, wie lässt man den Computer sie speichern? Egal, wie groß der Speicher des Computers ist, er kann nicht alles speichern, richtig! Er kann also keinen Wert relativ zur Mathematik speichern, sondern nur einen ungefähren Wert. Wenn der Computer ihn also speichert und dann zur Verwendung herausnimmt, treten Genauigkeitsprobleme auf.

JS übertrifft die Präzision der Zahlenlösung

1. Die maximale sichere Zahl in js ist Math.pow(2,53) - 1. Wenn die Zahl diesen Wert überschreitet, geht die Genauigkeit verloren. Sie können das Problem lösen, indem Sie die Zahl wie folgt in eine Zeichenfolge umwandeln:

// js maximale sichere Zahl: Math.pow(2, 53)-1

sei a = '123456444565456.889'
sei b = '121231456.32'
// a + b = '123456565796913.209'

Funktion addTwo(a, b) {
    //1. Vergleiche die Längen zweier Zahlen und füge der kürzeren Zahl eine 0 voran
    if (a.Länge > b.Länge) {
        lass arr = Array(a.Länge - b.Länge).fill(0);
        b = arr.join('') + b
    } sonst wenn (a.Länge < b.Länge) {
        lass arr = Array(b.Länge - a.Länge).fill(0);
        a = arr.join('') + a
    }

    //2. Kehren Sie die beiden Zahlen um (das liegt daran, dass die Leute daran gewöhnt sind, von links nach rechts zu addieren, Zahlen jedoch von rechts nach links addiert werden, sodass die Umkehrung leichter zu verstehen ist)
    a = a.split('').reverse();
    b = b.split('').reverse();

    //3. Durchlaufe zwei Arrays und addiere sie. Wenn die Summe größer als 10 ist, dann ist das Vorzeichen = 1 und der Wert an der aktuellen Position ist (Summe % 10).
    let sign = 0; //markiere, ob ein Übertrag vorhanden ist let newVal = []; //wird verwendet, um das Endergebnis zu speichern for (let j = 0; j < a.length; j++) {
        let val = a[j] / 1 + b[j] / 1 + sign; // Durch 1 teilen, um sicherzustellen, dass alles Zahlen sind. Sie können hier auch Number() verwenden.
        wenn (Wert >= 10) {
            Zeichen = 1;
            newVal.unshift(val % 10) // unshift wird hier anstelle von push verwendet, da es die Verwendung von reverse erspart
        } anders {
            Vorzeichen = 0;
            newVal.unshift(Wert)
        }
    }

    // Die letzte Addition muss eine Ziffer '1' enthalten
    returniere Vorzeichen && newVal.unshift(Vorzeichen) && newVal.join('') || newVal.join('')
}

// Siehe die prägnante Schreibweise anderer Freunde function addTwo(a,b) {
    lass temp = 0
    lass res = ''
    a = a.split('')
    b = b.split('')
    während(a.Länge || b.Länge || temp) {
        temp += Zahl(a.pop() || 0) + Zahl(b.pop() || 0)
        res = (temp%10) + res
        temp = temp > 9
    }
    returniere res.replace(/^0+/g, '')
}

2. Wenn es um das Hinzufügen von Dezimalteilen geht, kapseln Sie die obige Methode einmal und die vollständige Implementierung lautet wie folgt:

sei a = '123456444565456.889'
sei b = '121231456.32'
// a + b = '123456565796913.209'

Funktion addTwo(a = '0',b = '0', isHasDecimal=false) {
    //1. Vergleiche die Längen zweier Zahlen und füge der kürzeren Zahl eine 0 voran
    if (a.Länge > b.Länge) {
        lass arr = Array(a.Länge - b.Länge).fill(0);
        b = isHasDecimal && (b + arr.join('')) || arr.join('') + b
    } sonst wenn (a.Länge < b.Länge) {
        lass arr = Array(b.Länge - a.Länge).fill(0);
        a = isHasDecimal && (a + arr.join('')) || arr.join('') + a
    }

    //2. Kehren Sie die beiden Zahlen um (das liegt daran, dass die Leute daran gewöhnt sind, von links nach rechts zu addieren, Zahlen jedoch von rechts nach links addiert werden, sodass die Umkehrung leichter zu verstehen ist)
    a = a.split('').reverse();
    b = b.split('').reverse();


    //3. Durchlaufe zwei Arrays und addiere sie. Wenn die Summe größer als 10 ist, dann ist das Vorzeichen = 1 und der Wert an der aktuellen Position ist (Summe % 10).
    let sign = 0; //markiere, ob ein Übertrag vorhanden ist let newVal = []; //wird verwendet, um das Endergebnis zu speichern for (let j = 0; j < a.length; j++) {
        let val = a[j] / 1 + b[j] / 1 + sign; // Durch 1 teilen, um sicherzustellen, dass alles Zahlen sind. Sie können hier auch Number() verwenden.
        wenn (Wert >= 10) {
            Zeichen = 1;
            newVal.unshift(val % 10) // unshift wird hier anstelle von push verwendet, da es die Verwendung von reverse erspart
        } anders {
            Vorzeichen = 0;
            newVal.unshift(Wert)
        }
    }

    // Die letzte Addition muss eine Ziffer '1' enthalten
    returniere Vorzeichen && newVal.unshift(Vorzeichen) && newVal.join('') || newVal.join('')
}

Funktion add(a,b) {
    lass num1 = String(a).split('.')
    lass num2 = String(b).split('.')
    let intSum = addTwo(num1[0], num2[0])
    lass res = intSum

    wenn (Anzahl1.Länge>1 || Anzahl2.Länge > 1) {
        let decimalSum = addTwo(num1[1], num2[1], true)

        wenn (Dezimalsumme.Länge > (Zahl1[1]||'0').Länge && Dezimalsumme.Länge > (Zahl2[1]||'0').Länge) {
            intSum = addTwo(intSum, decimalSum[0])
            decimalSum = decimalSum.slice(1)
            res = `${intSum}.${decimalSum}`
        } anders {
            res = `${intSum}.${decimalSum}`
        }
    }
    Rückgabewert
}
console.log(add(a, b)) // 123456565796913.209
// konsole.log(add('325', '988')) // 1313

Sehen Sie sich einige typische Probleme mit dem Verlust digitaler Präzision bei JS an

// Ergänzung =======================
0,1 + 0,2 = 0,30000000000000004
0,7 + 0,1 = 0,799999999999999
0,2 + 0,4 = 0,6000000000000001

// Subtraktion =======================
1,5 - 1,2 = 0,30000000000000004
0,3 - 0,2 = 0,099999999999999998

// Multiplikation =======================
19,9 * 100 = 1989,99999999999998
0,8 * 3 = 2,4000000000000004
35,41 * 100 = 3540,99999999999995

// Abteilung =======================
0,3 / 0,1 = 2,99999999999999996
0,69 / 10 = 0,0689999999999999

Zusammenfassen

Dies ist das Ende dieses Artikels zur Lösung des Problems ungenauer Zahlen in JS. Weitere relevante Inhalte zu ungenauen Zahlen in JS finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den verwandten Artikeln weiter unten. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen!

Das könnte Sie auch interessieren:
  • Detaillierte Erklärung zur Vermeidung digitaler Berechnungsgenauigkeitsfehler in Javascript
  • So lösen Sie das Problem des Verlusts numerischer Präzision in JavaScript
  • Analyse und Lösung der Ursache des digitalen Präzisionsverlusts von JS

<<:  Installieren von MySQL 8.0.12 basierend auf Windows

>>:  Erfahren Sie, wie Sie ein Vue-Projekt mit Docker bereitstellen

Artikel empfehlen

Docker-Installation Tomcat Dubbo-Admin-Instanz-Kenntnisse

1. Laden Sie das Tomcat-Image herunter Docker zie...

Detailliertes Tutorial zur Installation von Docker auf CentOS 8

1. Frühere Versionen yum entfernen Docker Docker-...

Beispiel für die Implementierung der Hochverfügbarkeit von Keepalived+Nginx

1. Einführung in Keepalived Keepalived wurde ursp...

So ändern Sie die Standardcodierung von MySQL in Linux

Wenn während des Entwicklungsprozesses nach der W...

Einige Details zu MySQL-Indizes

Vor ein paar Tagen stellte mir ein Kollege eine F...

Mobile Web-Bildschirmanpassung (rem)

Vorwort Ich habe vor Kurzem meine bisherigen Noti...

Was Sie über Responsive Design wissen müssen

Responsive Design bedeutet, während des Website-E...

So verwenden Sie js, um festzustellen, ob eine Datei UTF-8-codiert ist

Konventionelle Lösung Verwenden Sie FileReader, u...

Foreman Ubuntu16 Schnellinstallation

Kurzanleitung Das Foreman-Installationsprogramm i...

Detaillierte Erläuterung der erweiterten Konstruktionseigenschaften von Vue

Inhaltsverzeichnis 1. Richtlinie Zollrichtlinie 2...

So installieren Sie Tomcat8 im Docker

1. Installieren Sie Tomcat8 mit Docker 1. Suchen ...