javascript - länge - title tag wordpress




Wie geht man mit der Fließkommazahlgenauigkeit in JavaScript um? (20)

Überraschenderweise wurde diese Funktion noch nicht veröffentlicht, obwohl andere ähnliche Varianten haben. Es stammt aus den MDN-Webdokumenten für Math.round (). Es ist prägnant und ermöglicht unterschiedliche Präzision.

function precisionRound(number, precision) {
  var factor = Math.pow(10, precision);
  return Math.round(number * factor) / factor;
}

console.log (precisionRound (1234.5678, 1)); // erwartete Ausgabe: 1234.6

console.log (precisionRound (1234.5678, -1)); // erwartete Ausgabe: 1230

var inp = document.querySelectorAll('input');
var btn = document.querySelector('button');

btn.onclick = function(){
  inp[2].value = precisionRound( parseFloat(inp[0].value) * parseFloat(inp[1].value) , 5 );
};

//MDN function
function precisionRound(number, precision) {
  var factor = Math.pow(10, precision);
  return Math.round(number * factor) / factor;
}
button{
display: block;
}
<input type='text' value='0.1'>
<input type='text' value='0.2'>
<button>Get Product</button>
<input type='text'>

Ich habe das folgende Dummy-Testskript:

function test(){
    var x = 0.1 * 0.2;
    document.write(x);
}
test();

Dies wird das Ergebnis 0.020000000000000004 während es nur 0.02 drucken soll (wenn Sie Ihren Taschenrechner verwenden). Soweit ich das verstanden habe, ist dies auf Fehler in der Gleitkomma-Multiplikationsgenauigkeit zurückzuführen.

Hat jemand eine gute Lösung damit ich in diesem Fall das korrekte Ergebnis 0.02 bekomme? Ich weiß, es gibt Funktionen wie toFixed oder Rounding wäre eine andere Möglichkeit, aber ich möchte wirklich die ganze Zahl ohne jede Kürzung und Rundung gedruckt haben. Ich wollte nur wissen, ob einer von euch eine schöne, elegante Lösung hat.

Natürlich werde ich sonst auf etwa 10 Ziffern runden.


0.6 * 3 es ist super!)) Für mich funktioniert das gut:

function dec( num )
{
    var p = 100;
    return Math.round( num * p ) / p;
}

Sehr sehr einfach))


Ausgabe mit folgender Funktion:

var toFixedCurrency = function(num){
    var num = (num).toString();
    var one = new RegExp(/\.\d{1}$/).test(num);
    var two = new RegExp(/\.\d{2,}/).test(num);
    var result = null;

    if(one){ result = num.replace(/\.(\d{1})$/, '.$10');
    } else if(two){ result = num.replace(/\.(\d{2})\d*/, '.$1');
    } else { result = num*100; }

    return result;
}

function test(){
    var x = 0.1 * 0.2;
    document.write(toFixedCurrency(x));
}

test();

toFixedCurrency(x) auf die Ausgabe toFixedCurrency(x) .


Beachten Sie, dass dieses Verhalten für die allgemeine Verwendung wahrscheinlich akzeptabel ist.
Das Problem tritt auf, wenn diese Gleitkommawerte verglichen werden, um eine geeignete Aktion zu bestimmen.
Mit dem Aufkommen von ES6 wird eine neue Konstante Number.EPSILON definiert, um die akzeptable Fehlerspanne zu bestimmen:
Also anstatt den Vergleich so zu machen

0.1 + 0.2 === 0.3 // which returns false

Sie können eine benutzerdefinierte Vergleichsfunktion wie folgt definieren:

function epsEqu(x, y) {
    return Math.abs(x - y) < Number.EPSILON;
}
console.log(epsEqu(0.1+0.2, 0.3)); // true

Quelle: http://2ality.com/2015/04/numbers-math-es6.html#numberepsilon


Benutzen

var x = 0.1*0.2;
 x =Math.round(x*Math.pow(10,2))/Math.pow(10,2);

Das Ergebnis, das Sie erhalten, ist korrekt und ziemlich konsistent über Fließkomma-Implementierungen in verschiedenen Sprachen, Prozessoren und Betriebssystemen - die einzige Sache, die sich ändert, ist das Ausmaß der Ungenauigkeit, wenn der Float tatsächlich ein Double (oder höher) ist.

0,1 in binären Fließkommazahlen ist wie 1/3 in Dezimal (dh 0,33333333333333 ... für immer), es gibt einfach keine genaue Art, damit umzugehen.

Wenn Sie mit Schwimmern zu tun haben, erwarten Sie immer kleine Rundungsfehler, also müssen Sie das angezeigte Ergebnis immer auf etwas Vernünftiges runden. Im Gegenzug erhalten Sie sehr, sehr schnelle und leistungsfähige Arithmetik, weil alle Berechnungen in der nativen Binärdatei des Prozessors sind.

Die meiste Zeit ist die Lösung nicht auf Festkommaarithmetik umzustellen, hauptsächlich weil es viel langsamer ist und in 99% der Fälle die Genauigkeit nicht benötigt wird. Wenn Sie mit Dingen zu tun haben, die diese Genauigkeit erfordern (zB finanzielle Transaktionen), ist Javascript wahrscheinlich nicht das beste Werkzeug, das Sie verwenden können (da Sie die Festkomma-Typen erzwingen wollen, ist eine statische Sprache wahrscheinlich besser ).

Sie suchen nach der eleganten Lösung, denn ich fürchte, das ist es: Schwebekörper sind schnell, haben aber kleine Rundungsfehler - immer etwas Sinnvolles bei der Anzeige ihrer Ergebnisse.


Die round () -Funktion bei phpjs.org funktioniert gut: http://phpjs.org/functions/round

num = .01 + .06;  // yields 0.0699999999999
rnum = round(num,12); // yields 0.07

Diese Funktion ermittelt aus der Multiplikation zweier Gleitkommazahlen die benötigte Genauigkeit und gibt ein Ergebnis mit der entsprechenden Genauigkeit zurück. Elegant, obwohl es nicht ist.

function multFloats(a,b){
  var atens = Math.pow(10,String(a).length - String(a).indexOf('.') - 1), 
      btens = Math.pow(10,String(b).length - String(b).indexOf('.') - 1); 
  return (a * atens) * (b * btens) / (atens * btens); 
}

Ich BigNumber.js erfüllt meine Bedürfnisse.

Eine JavaScript-Bibliothek für Dezimal und Nicht-Dezimal-Arithmetik mit beliebiger Genauigkeit.

Es hat eine gute documentation und der Autor reagiert sehr sorgfältig auf Feedback.

Derselbe Autor hat 2 andere ähnliche Bibliotheken:

Big.js

Eine kleine, schnelle JavaScript-Bibliothek für Dezimalarithmetik beliebiger Genauigkeit. Die kleine Schwester zu bignumber.js.

und Decimal.js

Dezimal-Typ mit beliebiger Genauigkeit für JavaScript.

Hier ist ein Code, der BigNumber verwendet:

$(function(){

  
  var product = BigNumber(.1).times(.2);  
  $('#product').text(product);

  var sum = BigNumber(.1).plus(.2);  
  $('#sum').text(sum);


});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<!-- 1.4.1 is not the current version, but works for this example. -->
<script src="http://cdn.bootcss.com/bignumber.js/1.4.1/bignumber.min.js"></script>

.1 &times; .2 = <span id="product"></span><br>
.1 &plus; .2 = <span id="sum"></span><br>


Ich bin nicht so gut in der Programmierung, aber war wirklich an diesem Thema interessiert, also habe ich versucht zu verstehen, wie man das löst, ohne irgendwelche Bibliotheken oder Skripte zu benutzen

Ich habe das auf Notizblock geschrieben

var toAlgebraic = function(f1, f2) {
    let f1_base = Math.pow(10, f1.split('.')[1].length);
    let f2_base = Math.pow(10, f2.split('.')[1].length);
    f1 = parseInt(f1.replace('.', ''));
    f2 = parseInt(f2.replace('.', ''));

    let dif, base;
    if (f1_base > f2_base) {
        dif = f1_base / f2_base;
        base = f1_base;
        f2 = f2 * dif;
    } else {
        dif = f2_base / f1_base;
        base = f2_base;
        f1 = f1 * dif;
    }

    return (f1 * f2) / base;
};

console.log(0.1 * 0.2);
console.log(toAlgebraic("0.1", "0.2"));

Sie müssen diesen Code möglicherweise umgestalten, da ich nicht gut programmieren kann :)


Ich mag die Lösung von Pedro Ladaria und verwende etwas Ähnliches.

function strip(number) {
    return (parseFloat(number).toPrecision(12));
}

Im Gegensatz zur Pedros-Lösung wird dies 0,999 ... wiederholen und ist genau auf plus / minus Eins an der niedrigstwertigen Stelle.

Hinweis: Wenn Sie mit 32 oder 64 Bit Gleitkommazahlen arbeiten, sollten Sie toPrecision (7) und toPrecision (15) für beste Ergebnisse verwenden. Sehen Sie sich diese Frage an, um zu erfahren, warum.


Machst du nur Multiplikation? Wenn ja, dann können Sie zu Ihrem Vorteil ein ordentliches Geheimnis über die Dezimalarithmetik verwenden. Das ist NumberOfDecimals(X) + NumberOfDecimals(Y) = ExpectedNumberOfDecimals . Das heißt, wenn wir 0.123 * 0.12 haben, wissen wir, dass es 5 Dezimalstellen geben wird, weil 0.123 3 Dezimalstellen hat und 0.12 2 Dezimalstellen. Also, wenn JavaScript uns eine Nummer wie 0.014760000002 , können wir sicher auf die 5. Dezimalstelle runden, ohne Angst haben zu müssen, die Genauigkeit zu verlieren.


Sehen Sie sich die Festkommaarithmetik an . Es wird wahrscheinlich Ihr Problem lösen, wenn der Zahlenbereich, den Sie bearbeiten möchten, klein ist (zB Währung). Ich würde es auf einige Dezimalwerte abrunden, was die einfachste Lösung ist.


Sie haben Recht, der Grund dafür ist die begrenzte Genauigkeit der Fließkommazahlen. Speichern Sie Ihre rationalen Zahlen als Division zweier Integer-Zahlen und in den meisten Situationen können Sie Zahlen ohne Präzisionsverlust speichern. Wenn es zum Drucken kommt, möchten Sie vielleicht das Ergebnis als Bruch anzeigen. Mit der von mir vorgeschlagenen Darstellung wird es trivial.

Natürlich hilft das nicht viel mit irrationalen Zahlen. Vielleicht möchten Sie jedoch Ihre Berechnungen so optimieren, dass sie das geringste Problem verursachen (z. B. das Erkennen von Situationen wie sqrt(3)^2) .



Sie müssen sich nur überlegen, wie viele Dezimalziffern Sie tatsächlich wollen - den Kuchen können Sie nicht essen und auch nicht essen :-)

Numerische Fehler häufen sich bei jeder weiteren Operation und wenn Sie es nicht frühzeitig abschneiden, wird es einfach wachsen. Numerische Bibliotheken, die saubere Ergebnisse liefern, schneiden die letzten 2 Ziffern bei jedem Schritt ab, numerische Koprozessoren haben aus dem gleichen Grund auch eine "normale" und "volle" Länge. Cuff-Offs sind billig für einen Prozessor, aber sehr teuer für Sie in einem Skript (Multiplizieren und Teilen und Verwenden von Pov (...)). Eine gute mathematische Bibliothek würde den Boden (x, n) liefern, um den Cut-Off für Sie zu machen.

Also sollten Sie zumindest global var / constant mit pov (10, n) machen - was bedeutet, dass Sie sich für die Präzision entschieden haben, die Sie brauchen :-)

Math.floor(x*PREC_LIM)/PREC_LIM  // floor - you are cutting off, not rounding

Sie könnten auch weiterhin Mathe machen und nur am Ende abschneiden - vorausgesetzt, Sie zeigen nur an und machen keine if-s mit Ergebnissen. Wenn Sie das tun können, dann .toFixed (...) könnte effizienter sein.

Wenn Sie if-s / comparises ausführen und nicht ausschneiden möchten, benötigen Sie auch eine kleine Konstante, die gewöhnlich als eps bezeichnet wird und eine Dezimalstelle höher als der maximal erwartete Fehler ist. Sagen Sie, dass Ihr Cut-Off die letzten zwei Dezimalstellen ist - dann hat Ihr eps 1 auf dem 3. Platz vom letzten (3. am wenigsten signifikanten) und Sie können es verwenden, um zu vergleichen, ob das Ergebnis innerhalb des erwarteten eps-Bereichs liegt (0.02 -eps <0.1 * 0,2 <0,02 + eps).


Um dies zu vermeiden, sollten Sie mit Integer-Werten anstelle von Gleitkommawerten arbeiten. Wenn Sie also 2 Positionen Präzision mit den Werten * 100 haben wollen, verwenden Sie für 3 Positionen 1000. Bei der Anzeige verwenden Sie einen Formatierer, um das Trennzeichen einzufügen.

Viele Systeme verzichten auf die Verwendung von Dezimalzahlen. Aus diesem Grund arbeiten viele Systeme mit Cents (als Integer) anstelle von Dollars / Euro (als Gleitkommazahl).


Verwenden Sie die Nummer (1.234443) .toFixed (2); es wird 1.23 drucken

function test(){
    var x = 0.1 * 0.2;
    document.write(Number(x).toFixed(2));
}
test();

Problem

Fließkomma kann nicht alle Dezimalwerte genau speichern. Bei Gleitkommaformaten treten daher immer Rundungsfehler bei den Eingabewerten auf. Die Fehler an den Eingängen führen natürlich zu Fehlern am Ausgang. Im Fall einer diskreten Funktion oder eines diskreten Operators kann es große Unterschiede zwischen dem Ausgang und dem Punkt geben, an dem die Funktion oder der Operator diskret ist.

Eingabe und Ausgabe von Fließkommawerten

Wenn Sie Fließkommavariablen verwenden, sollten Sie sich dessen immer bewusst sein. Und was immer Sie von einer Berechnung mit Gleitkommawerten erwarten, sollte immer formatiert / konditioniert werden, bevor Sie dies berücksichtigen.
Wenn nur kontinuierliche Funktionen und Operatoren verwendet werden, wird oft auf die gewünschte Genauigkeit gerundet (nicht abgeschnitten). Standardformatierungsfunktionen, die zum Konvertieren von Fließkommazahlen in Zeichenfolgen verwendet werden, erledigen dies normalerweise für Sie.
Da die Rundung einen Fehler hinzufügt, der dazu führen kann, dass der Gesamtfehler mehr als die Hälfte der gewünschten Genauigkeit beträgt, sollte die Ausgabe basierend auf der erwarteten Genauigkeit der Eingaben und der gewünschten Genauigkeit der Ausgabe korrigiert werden. Du solltest

  • Runden Sie Eingaben auf die erwartete Genauigkeit ab, oder stellen Sie sicher, dass keine Werte mit höherer Genauigkeit eingegeben werden können.
  • Fügen Sie den Ausgängen vor dem Runden / Formatieren einen kleinen Wert hinzu, der kleiner oder gleich 1/4 der gewünschten Genauigkeit und größer als der maximal erwartete Fehler ist, der durch Rundungsfehler bei der Eingabe und während der Berechnung verursacht wird. Wenn dies nicht möglich ist, reicht die Kombination der Genauigkeit des verwendeten Datentyps nicht aus, um die gewünschte Ausgabegenauigkeit für Ihre Berechnung zu liefern.

Diese zwei Dinge werden normalerweise nicht gemacht und in den meisten Fällen sind die Unterschiede, die dadurch verursacht werden, dass sie für die meisten Benutzer nicht wichtig sind, aber ich hatte bereits ein Projekt, bei dem die Ausgabe von den Benutzern ohne diese Korrekturen nicht akzeptiert wurde.

Diskrete Funktionen oder Operatoren (wie Modula)

Wenn diskrete Operatoren oder Funktionen beteiligt sind, sind möglicherweise zusätzliche Korrekturen erforderlich, um sicherzustellen, dass die Ausgabe wie erwartet erfolgt. Das Runden und Hinzufügen kleiner Korrekturen vor dem Runden kann das Problem nicht lösen.
Eine spezielle Überprüfung / Korrektur von Zwischenberechnungsresultaten unmittelbar nach dem Anwenden der diskreten Funktion oder des diskreten Operators könnte erforderlich sein. Für einen speziellen Fall (modula-Operator), siehe meine Antwort zu Frage: Warum gibt der Modulo-Operator eine Bruchzahl in Javascript zurück?

Besser vermeiden, das Problem zu haben

Es ist oft effizienter, diese Probleme zu vermeiden, indem Sie Datentypen (Ganzzahl- oder Festkommaformate) für Berechnungen wie diese verwenden, die die erwartete Eingabe ohne Rundungsfehler speichern können. Ein Beispiel dafür ist, dass Sie für Finanzberechnungen niemals Fließkommawerte verwenden sollten.


    You can use library https://github.com/MikeMcl/decimal.js/. 
    it will   help  lot to give proper solution. 
    javascript console output 95 *722228.630 /100 = 686117.1984999999
    decimal library implementation 
    var firstNumber = new Decimal(95);
    var secondNumber = new Decimal(722228.630);
    var thirdNumber = new Decimal(100);
    var partialOutput = firstNumber.times(secondNumber);
    console.log(partialOutput);
    var output = new Decimal(partialOutput).div(thirdNumber);
    alert(output.valueOf());
    console.log(output.valueOf())== 686117.1985




floating-point