it-swarm.com.de

Auf höchstens 2 Dezimalstellen runden (nur falls erforderlich)

Ich möchte höchstens 2 Nachkommastellen runden, aber nur wenn nötig.

Eingang:

10
1.7777777
9.1

Ausgabe:

10
1.78
9.1

Wie kann ich das in JavaScript machen?

2355
stinkycheeseman

Benutze Math.round(num * 100) / 100

2972
Brian Ustas

Wenn der Wert ein Texttyp ist:

parseFloat("123.456").toFixed(2);

Wenn der Wert eine Zahl ist:

var numb = 123.23454;
numb = numb.toFixed(2);

Ein Nachteil ist, dass Werte wie 1.5 "1.50" als Ausgabe ergeben. Ein von @minitech vorgeschlagener Fix:

var numb = 1.5;
numb = +numb.toFixed(2);
// Note the plus sign that drops any "extra" zeroes at the end.
// It changes the result (which is a string) into a number again (think "0 + foo"),
// which means that it uses only as many digits as necessary.

Es scheint, als wäre Math.round eine bessere Lösung. Aber es ist nicht! In einigen Fällen wird es NICHT rund korrekt:

Math.round(1.005 * 1000)/1000 // Returns 1 instead of expected 1.01!

toFixed () rundet in einigen Fällen auch NOT richtig (getestet in Chrome v.55.0.2883.87)!

Beispiele:

parseFloat("1.555").toFixed(2); // Returns 1.55 instead of 1.56.
parseFloat("1.5550").toFixed(2); // Returns 1.55 instead of 1.56.
// However, it will return correct result if you round 1.5551.
parseFloat("1.5551").toFixed(2); // Returns 1.56 as expected.

1.3555.toFixed(3) // Returns 1.355 instead of expected 1.356.
// However, it will return correct result if you round 1.35551.
1.35551.toFixed(2); // Returns 1.36 as expected.

Ich denke, das liegt daran, dass 1.555 tatsächlich so etwas wie Float 1.55499994 hinter den Kulissen ist.

Lösung 1 besteht darin, ein Skript mit dem erforderlichen Rundungsalgorithmus zu verwenden. Beispiel:

function roundNumber(num, scale) {
  if(!("" + num).includes("e")) {
    return +(Math.round(num + "e+" + scale)  + "e-" + scale);
  } else {
    var arr = ("" + num).split("e");
    var sig = ""
    if(+arr[1] + scale > 0) {
      sig = "+";
    }
    return +(Math.round(+arr[0] + "e" + sig + (+arr[1] + scale)) + "e-" + scale);
  }
}

https://plnkr.co/edit/uau8BlS1cqbvWPCHJeOy?p=preview

Lösung 2 besteht darin, Front-End-Berechnungen zu vermeiden und gerundete Werte vom Back-End-Server abzurufen.

2760
A Kunin

Sie können verwenden

function roundToTwo(num) {    
    return +(Math.round(num + "e+2")  + "e-2");
}

Ich fand dieses vorbei an MDN . Ihr Weg vermeidet das Problem mit 1.005, das erwähnt war.

roundToTwo(1.005)
1.01
roundToTwo(10)
10
roundToTwo(1.7777777)
1.78
roundToTwo(9.1)
9.1
roundToTwo(1234.5678)
1234.57
411
MarkG

Die Antwort von MarkG ist die richtige. Hier ist eine generische Erweiterung für eine beliebige Anzahl von Dezimalstellen.

Number.prototype.round = function(places) {
  return +(Math.round(this + "e+" + places)  + "e-" + places);
}

Verwendungszweck:

var n = 1.7777;    
n.round(2); // 1.78

Gerätetest:

it.only('should round floats to 2 places', function() {

  var cases = [
    { n: 10,      e: 10,    p:2 },
    { n: 1.7777,  e: 1.78,  p:2 },
    { n: 1.005,   e: 1.01,  p:2 },
    { n: 1.005,   e: 1,     p:0 },
    { n: 1.77777, e: 1.8,   p:1 }
  ]

  cases.forEach(function(testCase) {
    var r = testCase.n.round(testCase.p);
    assert.equal(r, testCase.e, 'didn\'t get right number');
  });
})
135
Lavamantis

Man kann .toFixed(NumberOfDecimalPlaces) verwenden.

var str = 10.234.toFixed(2); // => '10.23'
var number = Number(str); // => 10.23
79
Gourav Singla

Betrachten Sie .toFixed() und .toPrecision():

http://www.javascriptkit.com/javatutors/formatnumber.shtml

67
AceCorban

Diese Frage ist kompliziert.

Angenommen, wir haben eine Funktion, roundTo2DP(num), die ein Gleitkomma als Argument verwendet und einen auf zwei Dezimalstellen gerundeten Wert zurückgibt. Was soll jeder dieser Ausdrücke auswerten?

  • roundTo2DP(0.014999999999999999)
  • roundTo2DP(0.0150000000000000001)
  • roundTo2DP(0.015)

Die "offensichtliche" Antwort lautet, dass das erste Beispiel auf 0,01 runden sollte (weil es näher an 0,01 als an 0,02 liegt), während die anderen beiden auf 0,02 runden sollten (weil 0,0150000000000000001 näher an 0,02 als an 0,01 liegt und weil 0,015 genau in der Mitte dazwischen liegt sie und es gibt eine mathematische Konvention, dass solche Zahlen aufgerundet werden).

Der Haken, den Sie vielleicht erraten haben, ist, dass roundTo2DPnmöglich implementiert werden kann, um diese offensichtlichen Antworten zu geben, da alle drei übergebenen Zahlen dieselbe Zahl sind =. Binäre Gleitkommazahlen nach IEEE 754 (die Art, die von JavaScript verwendet wird) können die meisten nicht ganzzahligen Zahlen nicht genau darstellen. Daher werden alle drei oben genannten numerischen Literale auf eine in der Nähe gültige Gleitkommazahl gerundet. Diese Zahl ist zufällig gena

0.01499999999999999944488848768742172978818416595458984375

das ist näher an 0,01 als an 0,02.

Sie können sehen, dass alle drei Zahlen in Ihrer Browserkonsole, in der Node Shell oder in einem anderen JavaScript-Interpreter gleich sind. Vergleichen Sie sie einfach:

> 0.014999999999999999 === 0.0150000000000000001
true

Wenn ich also m = 0.0150000000000000001 schreibe, ist der genaue Wert von m, mit dem ich ende, näher an 0.01 als an 0.02. Und doch, wenn ich m in einen String konvertiere ...

> var m = 0.0150000000000000001;
> console.log(String(m));
0.015
> var m = 0.014999999999999999;
> console.log(String(m));
0.015

... Ich erhalte 0,015, was auf 0,02 runden sollte und was merklich ist nicht ​​die 56-Dezimalstellen-Zahl Ich sagte früher, dass alle diese Zahlen genau gleich waren. Was für eine dunkle Magie ist das?

Die Antwort finden Sie in der ECMAScript-Spezifikation in Abschnitt 7.1.12.1: Auf den Nummerntyp angewendeter ToString . Hier werden die Regeln für die Umwandlung einer Zahl m in einen String festgelegt. Der Schlüsselteil ist Punkt 5, in dem eine Ganzzahl s generiert wird, deren Ziffern in der Zeichenfolgendarstellung von m verwendet werden:

sei n, k und s ganze Zahlen, so dass k ≥ 1, 10k-1 ≤ s <10k, der Zahlenwert für s × 10n-k ist m und k ist so klein wie möglich. Beachten Sie, dass k die Anzahl der Stellen in der Dezimaldarstellung von s ist, dass s nicht durch 10 teilbar ist und dass die niedrigstwertige Stelle von s wird durch diese Kriterien nicht unbedingt eindeutig bestimmt.

Der entscheidende Teil hier ist die Anforderung, dass "k so klein wie möglich ist". Was diese Anforderung ausmacht, ist eine Anforderung, dass der Wert von String(m) bei gegebener Zahl mdie geringstmögliche Anzahl von Ziffern haben muss, während die Anforderung, dass Number(String(m)) === m noch erfüllt ist. Da wir bereits wissen, dass 0.015 === 0.0150000000000000001, ist jetzt klar, warum String(0.0150000000000000001) === '0.015' wahr sein muss.

Natürlich hat keine dieser Diskussionen direkt geantwortet, was roundTo2DP(m)should zurückgibt. Wenn der genaue Wert von m 0.01499999999999999944488848768742172978818416595458984375 ist, aber die Zeichenfolgendarstellung '0.015' ist, was ist dann die richtige Antwort - mathematisch, praktisch, philosophisch oder was auch immer - wenn wir sie auf zwei Dezimalstellen runden?

Darauf gibt es keine einzige richtige Antwort. Dies hängt von Ihrem Anwendungsfall ab. Sie möchten wahrscheinlich die String-Darstellung respektieren und aufrunden, wenn:

  • Der dargestellte Wert ist von Natur aus diskret, z. Ein Währungsbetrag in einer 3-Dezimal-Währung wie Dinar. In diesem Fall ist der Wert true einer Zahl wie 0.015 is 0.015 und die Darstellung 0.0149999999 ..., die im binären Gleitkomma erhalten wird, ein Rundungsfehler. (Natürlich werden viele argumentieren, dass Sie für die Behandlung solcher Werte eine Dezimalbibliothek verwenden sollten und sie niemals als binäre Gleitkommazahlen darstellen sollten.)
  • Der Wert wurde von einem Benutzer eingegeben. Auch in diesem Fall ist die genaue eingegebene Dezimalzahl wahrer als die nächste binäre Gleitkommadarstellung.

Auf der anderen Seite möchten Sie wahrscheinlich den binären Gleitkommawert respektieren und abrunden, wenn Ihr Wert von einer inhärent kontinuierlichen Skala stammt - zum Beispiel, wenn es sich um einen Messwert von einem Sensor handelt.

Diese beiden Ansätze erfordern unterschiedlichen Code. Um die Zeichenfolgendarstellung der Zahl zu respektieren, können wir (mit einigem relativ subtilen Code) unsere eigene Rundung implementieren, die sich direkt auf die Zeichenfolgendarstellung auswirkt, Ziffer für Ziffer, wobei derselbe Algorithmus verwendet wird, den Sie in der Schule verwendet haben wurden gelehrt, wie man Zahlen rundet. Im Folgenden finden Sie ein Beispiel, das die Anforderung des OP erfüllt, die Zahl "nur bei Bedarf" auf 2 Dezimalstellen darzustellen, indem nach dem Dezimalpunkt folgende Nullen entfernt werden. Möglicherweise müssen Sie es natürlich an Ihre spezifischen Anforderungen anpassen.

/**
 * Converts num to a decimal string (if it isn't one already) and then rounds it
 * to at most dp decimal places.
 *
 * For explanation of why you'd want to perform rounding operations on a String
 * rather than a Number, see http://stackoverflow.com/a/38676273/1709587
 *
 * @param {(number|string)} num
 * @param {number} dp
 * @return {string}
 */
function roundStringNumberWithoutTrailingZeroes (num, dp) {
    if (arguments.length != 2) throw new Error("2 arguments required");

    num = String(num);
    if (num.indexOf('e+') != -1) {
        // Can't round numbers this large because their string representation
        // contains an exponent, like 9.99e+37
        throw new Error("num too large");
    }
    if (num.indexOf('.') == -1) {
        // Nothing to do
        return num;
    }

    var parts = num.split('.'),
        beforePoint = parts[0],
        afterPoint = parts[1],
        shouldRoundUp = afterPoint[dp] >= 5,
        finalNumber;

    afterPoint = afterPoint.slice(0, dp);
    if (!shouldRoundUp) {
        finalNumber = beforePoint + '.' + afterPoint;
    } else if (/^9+$/.test(afterPoint)) {
        // If we need to round up a number like 1.9999, increment the integer
        // before the decimal point and discard the fractional part.
        finalNumber = Number(beforePoint)+1;
    } else {
        // Starting from the last digit, increment digits until we find one
        // that is not 9, then stop
        var i = dp-1;
        while (true) {
            if (afterPoint[i] == '9') {
                afterPoint = afterPoint.substr(0, i) +
                             '0' +
                             afterPoint.substr(i+1);
                i--;
            } else {
                afterPoint = afterPoint.substr(0, i) +
                             (Number(afterPoint[i]) + 1) +
                             afterPoint.substr(i+1);
                break;
            }
        }

        finalNumber = beforePoint + '.' + afterPoint;
    }

    // Remove trailing zeroes from fractional part before returning
    return finalNumber.replace(/0+$/, '')
}

Anwendungsbeispiel:

> roundStringNumberWithoutTrailingZeroes(1.6, 2)
'1.6'
> roundStringNumberWithoutTrailingZeroes(10000, 2)
'10000'
> roundStringNumberWithoutTrailingZeroes(0.015, 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes('0.015000', 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes(1, 1)
'1'
> roundStringNumberWithoutTrailingZeroes('0.015', 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes(0.01499999999999999944488848768742172978818416595458984375, 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes('0.01499999999999999944488848768742172978818416595458984375', 2)
'0.01'

Die obige Funktion ist wahrscheinlich das, was Sie verwenden möchten, um zu vermeiden, dass Benutzer jemals Zeuge von Zahlen werden, die sie eingegeben haben, und die falsch gerundet sind.

(Alternativ können Sie auch die Bibliothek round1 verwenden, die eine ähnlich verhaltende Funktion mit einer völlig anderen Implementierung bietet.)

Aber was ist, wenn Sie die zweite Art von Zahl haben - einen Wert, der von einer kontinuierlichen Skala stammt, bei der es keinen Grund gibt, anzunehmen, dass ungefähre Dezimaldarstellungen mit weniger Dezimalstellen genauer sind gena als solche mit mehr? In diesem Fall möchten wir nicht ​​die String-Darstellung berücksichtigen, da diese Darstellung (wie in der Spezifikation erläutert) bereits gerundet ist. Wir wollen nicht den Fehler machen, "0.014999999 ... 375 rundet auf 0.015, was auf 0.02 rundet, also 0.014999999 ... 375 rundet auf 0.02".

Hier können wir einfach die eingebaute toFixed Methode verwenden. Beachten Sie, dass wir durch den Aufruf von Number() für den von toFixed zurückgegebenen String eine Zahl erhalten, deren String-Darstellung keine nachgestellten Nullen enthält (dank der Art und Weise, wie JavaScript die String-Darstellung einer Zahl berechnet, die weiter oben in dieser Antwort beschrieben wurde).

/**
 * Takes a float and rounds it to at most dp decimal places. For example
 *
 *     roundFloatNumberWithoutTrailingZeroes(1.2345, 3)
 *
 * returns 1.234
 *
 * Note that since this treats the value passed to it as a floating point
 * number, it will have counterintuitive results in some cases. For instance,
 * 
 *     roundFloatNumberWithoutTrailingZeroes(0.015, 2)
 *
 * gives 0.01 where 0.02 might be expected. For an explanation of why, see
 * http://stackoverflow.com/a/38676273/1709587. You may want to consider using the
 * roundStringNumberWithoutTrailingZeroes function there instead.
 *
 * @param {number} num
 * @param {number} dp
 * @return {number}
 */
function roundFloatNumberWithoutTrailingZeroes (num, dp) {
    var numToFixedDp = Number(num).toFixed(dp);
    return Number(numToFixedDp);
}
66
Mark Amery

Eine präzise Rundungsmethode. Quelle: Mozilla

(function(){

    /**
     * Decimal adjustment of a number.
     *
     * @param   {String}    type    The type of adjustment.
     * @param   {Number}    value   The number.
     * @param   {Integer}   exp     The exponent (the 10 logarithm of the adjustment base).
     * @returns {Number}            The adjusted value.
     */
    function decimalAdjust(type, value, exp) {
        // If the exp is undefined or zero...
        if (typeof exp === 'undefined' || +exp === 0) {
            return Math[type](value);
        }
        value = +value;
        exp = +exp;
        // If the value is not a number or the exp is not an integer...
        if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
            return NaN;
        }
        // Shift
        value = value.toString().split('e');
        value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp)));
        // Shift back
        value = value.toString().split('e');
        return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp));
    }

    // Decimal round
    if (!Math.round10) {
        Math.round10 = function(value, exp) {
            return decimalAdjust('round', value, exp);
        };
    }
    // Decimal floor
    if (!Math.floor10) {
        Math.floor10 = function(value, exp) {
            return decimalAdjust('floor', value, exp);
        };
    }
    // Decimal ceil
    if (!Math.ceil10) {
        Math.ceil10 = function(value, exp) {
            return decimalAdjust('ceil', value, exp);
        };
    }
})();

Beispiele:

// Round
Math.round10(55.55, -1); // 55.6
Math.round10(55.549, -1); // 55.5
Math.round10(55, 1); // 60
Math.round10(54.9, 1); // 50
Math.round10(-55.55, -1); // -55.5
Math.round10(-55.551, -1); // -55.6
Math.round10(-55, 1); // -50
Math.round10(-55.1, 1); // -60
Math.round10(1.005, -2); // 1.01 -- compare this with Math.round(1.005*100)/100 above
// Floor
Math.floor10(55.59, -1); // 55.5
Math.floor10(59, 1); // 50
Math.floor10(-55.51, -1); // -55.6
Math.floor10(-51, 1); // -60
// Ceil
Math.ceil10(55.51, -1); // 55.6
Math.ceil10(51, 1); // 60
Math.ceil10(-55.59, -1); // -55.5
Math.ceil10(-59, 1); // -50
62
user

Keine der hier gefundenen Antworten ist richtig. @stinkycheeseman bat um aufrunden, Sie alle rundeten die Zahl.

Verwenden Sie zum Aufrunden Folgendes:

Math.ceil(num * 100)/100;
58
machineaddict

Du solltest benutzen:

_Math.round( num * 100 + Number.EPSILON ) / 100
_

Niemand scheint sich dessen bewusst zu sein Number.EPSILON .

Es ist auch erwähnenswert, dass dies keine JavaScript-Verrücktheit ist, wie einige Leute sagten.

So funktionieren Gleitkommazahlen in einem Computer. Wie 99% der Programmiersprachen verfügt JavaScript nicht über . hausgemachte Gleitkommazahlen; es ist dafür auf die CPU/FPU angewiesen. Ein Computer verwendet Binärdateien, und in Binärdateien gibt es keine Zahlen wie _0.1_, sondern lediglich eine binäre Annäherung. Warum? Aus dem gleichen Grund kann 1/3 nicht als Dezimalzahl geschrieben werden: sein Wert ist 0,33333333 ... mit einer Unendlichkeit von drei.

Hier kommt Number.EPSILON . Diese Zahl ist die Differenz zwischen 1 und der nächsten Zahl, die in Gleitkommazahlen mit doppelter Genauigkeit vorhanden ist. Das war's: Es gibt keine Nummer zwischen _1_ und 1 + _Number.EPSILON_.

EDIT:

Lassen Sie uns eines klarstellen, wie in den Kommentaren gefordert: Das Hinzufügen von _Number.EPSILON_ ist nur relevant, wenn der zu rundende Wert das Ergebnis einer arithmetischen Operation ist, da er ein Gleitkomma-Fehler-Delta verschlucken kann.

Es ist nicht sinnvoll, wenn der Wert aus einer direkten Quelle stammt (z. B. Literal, Benutzereingabe oder Sensor).

EDIT (2019):

Wie @maganap und einige Leute bereits erwähnt haben, ist es am besten, vor der Multiplikation Number.EPSILON hinzuzufügen:

_Math.round( ( num + Number.EPSILON ) * 100 ) / 100
_
57
cronvel

Hier ist eine einfache Möglichkeit, dies zu tun:

Math.round(value * 100) / 100

Möglicherweise möchten Sie jedoch eine separate Funktion erstellen, die dies für Sie erledigt:

function roundToTwo(value) {
    return(Math.round(value * 100) / 100);
}

Dann würden Sie einfach den Wert übergeben.

Sie können die Rundung auf eine beliebige Anzahl von Dezimalstellen erweitern, indem Sie einen zweiten Parameter hinzufügen.

function myRound(value, places) {
    var multiplier = Math.pow(10, places);

    return (Math.round(value * multiplier) / multiplier);
}
45
JayDM

Für mich Math.round () gab nicht die richtige Antwort. Ich fand toFixed (2) funktioniert besser. Nachfolgend finden Sie Beispiele für beide:

console.log(Math.round(43000 / 80000) * 100); // wrong answer

console.log(((43000 / 80000) * 100).toFixed(2)); // correct answer
36
VicJordan
+(10).toFixed(2); // = 10
+(10.12345).toFixed(2); // = 10.12

(10).toFixed(2); // = 10.00
(10.12345).toFixed(2); // = 10.12
36
user3711536

Verwenden Sie diese Funktion Number(x).toFixed(2);

34
Harish.bazee

2017
Verwenden Sie einfach den nativen Code .toFixed()

number = 1.2345;
number.toFixed(2) // "1.23"

Wenn Sie streng sein und bei Bedarf Ziffern hinzufügen müssen, können Sie replace verwenden.

number = 1; // "1"
number.toFixed(5).replace(/\.?0*$/g,'');
33
pery mimon

Versuchen Sie dies geringes Gewicht Lösung:

function round(x, digits){
  return parseFloat(x.toFixed(digits))
}

 round(1.222,  2) ;
 // 1.22
 round(1.222, 10) ;
 // 1.222
32
petermeissner

Dafür gibt es verschiedene Möglichkeiten. Für Leute wie mich die Lodash-Variante

function round(number, precision) {
    var pair = (number + 'e').split('e')
    var value = Math.round(pair[0] + 'e' + (+pair[1] + precision))
    pair = (value + 'e').split('e')
    return +(pair[0] + 'e' + (+pair[1] - precision))
}

Verwendung:

round(0.015, 2) // 0.02
round(1.005, 2) // 1.01

Wenn Ihr Projekt jQuery oder lodash verwendet, finden Sie in den Bibliotheken auch die richtige round -Methode.

Update 1

Ich habe die Variante n.toFixed(2) entfernt, weil sie nicht korrekt ist. Vielen Dank an avalanche1

28
stanleyxu2005

MarkG und Lavamantis boten eine viel bessere Lösung als die angenommene. Es ist eine Schande, dass sie nicht mehr Stimmen bekommen!

Hier ist die Funktion, die ich benutze, um die Probleme mit Gleitkomma-Dezimalstellen zu lösen auch basierend auf MDN . Es ist noch allgemeiner (aber weniger präzise) als die Lösung von Lavamantis:

function round(value, exp) {
  if (typeof exp === 'undefined' || +exp === 0)
    return Math.round(value);

  value = +value;
  exp  = +exp;

  if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
    return NaN;

  // Shift
  value = value.toString().split('e');
  value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)));

  // Shift back
  value = value.toString().split('e');
  return +(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp));
}

Verwenden Sie es mit:

round(10.8034, 2);      // Returns 10.8
round(1.275, 2);        // Returns 1.28
round(1.27499, 2);      // Returns 1.27
round(1.2345678e+2, 2); // Returns 123.46

Im Vergleich zu Lavamantis können wir ...

round(1234.5678, -2); // Returns 1200
round("123.45");      // Returns 123
22
astorije

Wenn Sie die Lodash-Bibliothek verwenden, können Sie die runde Lodash-Methode wie folgt verwenden.

_.round(number, precision)

Z.B:

_.round(1.7777777, 2) = 1.78
21
Madura Pradeep

Seit ES6 gibt es einen "richtigen" Weg (ohne Statik zu überschreiben und Workarounds zu erstellen), um dies mit nter Verwendung von toPrecision zu tun

var x = 1.49999999999;
console.log(x.toPrecision(4));
console.log(x.toPrecision(3));
console.log(x.toPrecision(2));

var y = Math.PI;
console.log(y.toPrecision(6));
console.log(y.toPrecision(5));
console.log(y.toPrecision(4));

var z = 222.987654
console.log(z.toPrecision(6));
console.log(z.toPrecision(5));
console.log(z.toPrecision(4));

dann kannst du einfach parseFloat und Nullen werden 'verschwinden'.

console.log(parseFloat((1.4999).toPrecision(3)));
console.log(parseFloat((1.005).toPrecision(3)));
console.log(parseFloat((1.0051).toPrecision(3)));
19

Dies kann Ihnen helfen:

var result = (Math.round(input*100)/100);

weitere Informationen finden Sie unter diesem Link

Math.round (num) vs num.toFixed (0) und Browser-Inkonsistenzen

18
totten
var roundUpto = function(number, upto){
    return Number(number.toFixed(upto));
}
roundUpto(0.1464676, 2);

toFixed(2) hier 2 ist die Anzahl der Stellen, auf die diese Zahl gerundet werden soll.

16
Ritesh Dhuri

Es kann für Sie arbeiten,

Math.round(num * 100)/100;

den Unterschied zwischen toFixed und round kennen. Sie können sich Math.round (num) vs num.toFixed (0) und Browser-Inkonsistenzen ansehen.

15
Shreedhar

Einfachster Weg:

+num.toFixed(2)

Es konvertiert es in einen String und dann zurück in eine Ganzzahl/Fließkommazahl.

13
Edmund

Verwenden Sie so etwas wie "parseFloat (parseFloat (value) .toFixed (2))"

parseFloat(parseFloat("1.7777777").toFixed(2))-->1.78 
parseFloat(parseFloat("10").toFixed(2))-->10 
parseFloat(parseFloat("9.1").toFixed(2))-->9.1
13
Arulraj

Hier ist eine Prototypmethode:

Number.prototype.round = function(places){
    places = Math.pow(10, places); 
    return Math.round(this * places)/places;
}

var yournum = 10.55555;
yournum = yournum.round(2);
12
arielf

Im Allgemeinen erfolgt die Rundung durch Skalierung: round(num / p) * p

Bei Verwendung der Exponentialschreibweise wird die Rundung von + ve Zahlen korrekt durchgeführt. Diese Methode rundet Edge-Fälle jedoch nicht korrekt ab.

function round(num, precision = 2) {
        var scaled = Math.round(num + "e" + precision);
        return Number(scaled + "e" + -precision);
}

// testing some Edge cases
console.log( round(1.005, 2) );  // 1.01 correct
console.log( round(2.175, 2) );  // 2.18 correct
console.log( round(5.015, 2) );  // 5.02 correct

console.log( round(-1.005, 2) );  // -1    wrong
console.log( round(-2.175, 2) );  // -2.17 wrong
console.log( round(-5.015, 2) );  // -5.01 wrong

Hier ist auch eine Funktion, die ich geschrieben habe, um das Rechnen richtig zu runden. Sie können es selbst testen.

/**
 * MidpointRounding away from zero ('arithmetic' rounding)
 * Uses a half-epsilon for correction. (This offsets IEEE-754
 * half-to-even rounding that was applied at the Edge cases).
 */

function RoundCorrect(num, precision = 2) {
        // half epsilon to correct Edge cases.
        var c = 0.5 * Number.EPSILON * num;
//      var p = Math.pow(10, precision); //slow
        var p = 1; while (precision--> 0) p *= 10;
        if (num < 0)
                p *= -1;
        return Math.round((num + c) * p) / p;
}

// testing some Edge cases
console.log(RoundCorrect(1.005, 2));  // 1.01 correct
console.log(RoundCorrect(2.175, 2));  // 2.18 correct
console.log(RoundCorrect(5.015, 2));  // 5.02 correct

console.log(RoundCorrect(-1.005, 2));  // -1.01 correct
console.log(RoundCorrect(-2.175, 2));  // -2.18 correct
console.log(RoundCorrect(-5.015, 2));  // -5.02 correct
11
Amr Ali

Verwenden Sie diese Variante, um nicht mit vielen Nullen umzugehen:

Math.round(num * 1e2) / 1e2
10
Daniel De León

Wenn Sie die d3-Bibliothek bereits verwenden, verfügen sie über eine leistungsstarke Zahlenformatierungsbibliothek: https://github.com/mbostock/d3/wiki/Formatting

Die Rundung finden Sie hier: https://github.com/mbostock/d3/wiki/Formatting#d3_round

In Ihrem Fall lautet die Antwort:

> d3.round(1.777777, 2)
1.78
> d3.round(1.7, 2)
1.7
> d3.round(1, 2)
1
9
Scott Stafford

Eine Möglichkeit, eine solche Rundung nur bei Bedarf zu erzielen, besteht darin, Number.prototype.toLocaleString () zu verwenden:

myNumber.toLocaleString('en', {maximumFractionDigits:2, useGrouping:false})

Dies liefert genau die Ausgabe, die Sie erwarten, jedoch als Zeichenfolge. Sie können diese weiterhin in Zahlen umwandeln, wenn dies nicht der erwartete Datentyp ist.

9
Javarome

Ein einfacherer ES6-Weg ist

const round = (x, n) => 
  parseFloat(Math.round(x * Math.pow(10, n)) / Math.pow(10, n)).toFixed(n);

Dieses Muster gibt auch die angeforderte Genauigkeit zurück.

ex:

round(44.7826456, 4)  // yields 44.7826
round(78.12, 4)       // yields 78.1200
8
Adam A.

Ein anderer Ansatz ist die Verwendung einer Bibliothek. Warum nicht lodash:

const _ = require("lodash")
const roundedNumber = _.round(originalNumber, 2)
8
Carlos Lombardi

Einfache Lösung wäre, lodashs Ceil-Funktion zu verwenden, wenn Sie abrunden möchten ...

https://lodash.com/docs/4.17.10#ceil

_.round(6.001,2)

gibt 6

_.ceil(6.001, 2);

ergibt 6.01

_.ceil(37.4929,2);

ergibt 37,5

_.round(37.4929,2);

ergibt 37,49

8

parseFloat ("1.555"). toFixed (2); // Gibt 1,55 statt 1,56 zurück.

1,55 ist das absolut korrekte Ergebnis, da es im Computer keine exakte Darstellung von 1,555 gibt. Beim Lesen von 1,555 wird auf den nächstmöglichen Wert gerundet = 1,554999999999994 (64-Bit-Float). Und die Rundung dieser Zahl mit toFixed (2) ergibt 1,55.

Alle anderen hier zur Verfügung gestellten Funktionen führen zu einem Fehler, wenn der Eingang 1.55499999999999 ist.

Lösung: Fügen Sie vor dem Scannen die Ziffer "5" hinzu, um die Zahl zu runden (genauer: von 0 abzurunden). Tun Sie dies nur, wenn die Zahl wirklich ein Gleitkomma ist (ein Dezimalpunkt hat).

parseFloat("1.555"+"5").toFixed(2); // Returns 1.56
7
Wiimm

Dies ist die einfachste und eleganteste Lösung (und ich bin die beste der Welt;):

function roundToX(num, X) {    
    return +(Math.round(num + "e+"+X)  + "e-"+X);
}
//roundToX(66.66666666,2) => 66.67
//roundToX(10,2) => 10
//roundToX(10.904,2) => 10.9
7

Ich werde noch einen Ansatz hinzufügen.

number = 16.6666666;
console.log(parseFloat(number.toFixed(2)));
"16.67"

number = 16.6;
console.log(parseFloat(number.toFixed(2)));
"16.6"

number = 16;
console.log(parseFloat(number.toFixed(2)));
"16"

.toFixed(2) gibt eine Zeichenfolge mit genau 2 Dezimalstellen zurück, die möglicherweise hinter Nullen stehen oder nicht. Durch Ausführen von parseFloat() werden diese nachgestellten Nullen entfernt.

7
Marcos Lima

Basierend auf der gewählte Antwort und der hochgeladene Kommentar zu derselben Frage:

Math.round((num + 0.00001) * 100) / 100

Dies funktioniert für beide Beispiele:

Math.round((1.005 + 0.00001) * 100) / 100

Math.round((1.0049 + 0.00001) * 100) / 100
7
Fellow Stranger

Nachdem Sie verschiedene Iterationen aller möglichen Methoden durchlaufen haben, um eine wirklich genaue Genauigkeit der Dezimalrundung zu erzielen, ist es klar, dass die genaueste und effizienteste Lösung die Verwendung von Number.EPSILON ist. Dies bietet eine echte mathematische Lösung für das Problem der Gleitkomma-Genauigkeit. Es kann wie hier gezeigt einfach mehrfach ausgefüllt werden: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON um alle verbleibenden zu unterstützen IE Benutzer (dann sollten wir vielleicht wieder damit aufhören).

Angepasst an die hier bereitgestellte Lösung: https://stackoverflow.com/a/48850944/6910392

Eine einfache Drop-In-Lösung, die genaue Dezimalrundungen, Bodenbeläge und Decken mit einer optionalen Präzisionsvariablen liefert, ohne eine ganze Bibliothek hinzuzufügen.

var DecimalPrecision = (function(){
        if (Number.EPSILON === undefined) {
            Number.EPSILON = Math.pow(2, -52);
        }
        this.round = function(n, p=2){
            let r = 0.5 * Number.EPSILON * n;
            let o = 1; while(p-- > 0) o *= 10;
            if(n < 0)
                o *= -1;
            return Math.round((n + r) * o) / o;
        }
        this.ceil = function(n, p=2){
            let r = 0.5 * Number.EPSILON * n;
            let o = 1; while(p-- > 0) o *= 10;
            if(n < 0)
                o *= -1;
            return Math.ceil((n + r) * o) / o;
        }
        this.floor = function(n, p=2){
            let r = 0.5 * Number.EPSILON * n;
            let o = 1; while(p-- > 0) o *= 10;
            if(n < 0)
                o *= -1;
            return Math.floor((n + r) * o) / o;
        }
        return this;
    })();
    console.log(DecimalPrecision.round(1.005));
    console.log(DecimalPrecision.ceil(1.005));
    console.log(DecimalPrecision.floor(1.005));
    console.log(DecimalPrecision.round(1.0049999));
    console.log(DecimalPrecision.ceil(1.0049999));
    console.log(DecimalPrecision.floor(1.0049999));
    console.log(DecimalPrecision.round(2.175495134384,7));
    console.log(DecimalPrecision.round(2.1753543549,8));
    console.log(DecimalPrecision.round(2.1755465135353,4));
6
KFish

Behalten Sie den Typ als Ganzzahl für spätere Sortierungen oder andere mathematische Operationen bei:

Math.round(1.7777777 * 100)/100

1,78

// Round up!
Math.ceil(1.7777777 * 100)/100 

1,78

// Round down!
Math.floor(1.7777777 * 100)/100

1,77

Oder in einen String konvertieren:

(1.7777777).toFixed(2)

"1.77"

6
profimedica

Ich weiß, dass es viele Antworten gibt, aber die meisten von ihnen haben in bestimmten Fällen Nebenwirkungen.

Die einfachste und kürzeste Lösung ohne Nebenwirkungen ist folgende:

Number((2.3456789).toFixed(2)) // 2.35

Es rundet richtig und gibt eine Zahl anstelle eines Strings zurück

console.log(Number((2.345).toFixed(2)))  // 2.35
console.log(Number((2.344).toFixed(2)))  // 2.34
console.log(Number((2).toFixed(2)))      // 2
console.log(Number((-2).toFixed(2)))     // -2
console.log(Number((-2.345).toFixed(2))) // -2.35

console.log(Number((2.345678).toFixed(3))) // 2.346
6
Nicolo

Dies hat den Trick für mich gemacht (TypeScript):

round(decimal: number, decimalPoints: number): number{
    let roundedValue = Math.round(decimal * Math.pow(10, decimalPoints)) / Math.pow(10, decimalPoints);

    console.log(`Rounded ${decimal} to ${roundedValue}`);
    return roundedValue;
}

// Sample output:
Rounded 18.339840000000436 to 18.34
Rounded 52.48283999999984 to 52.48
Rounded 57.24612000000036 to 57.25
Rounded 23.068320000000142 to 23.07
Rounded 7.792980000000398 to 7.79
Rounded 31.54157999999981 to 31.54
Rounded 36.79686000000004 to 36.8
Rounded 34.723080000000124 to 34.72
Rounded 8.4375 to 8.44
Rounded 15.666960000000074 to 15.67
Rounded 29.531279999999924 to 29.53
Rounded 8.277420000000006 to 8.28
5
Ross

Ich habe einen einfachen tipCalculator erstellt und es gab viele Antworten, die das Problem zu komplizieren scheinen. Daher empfand ich das Zusammenfassen des Problems als die beste Möglichkeit, diese Frage wirklich zu beantworten

wenn Sie eine gerundete Dezimalzahl erstellen möchten, rufen Sie zuerst toFixed(# of decimal places you want to keep) auf und setzen diese dann in eine Zahl ()

so Endergebnis:

let amountDue = 286.44;
tip = Number((amountDue * 0.2).toFixed(2));
console.log(tip)  // 57.29 instead of 57.288
4
Denis S Dujota

Hier ist die kürzeste und vollständige Antwort:

function round(num, decimals) {
        var n = Math.pow(10, decimals);
        return Math.round( (n * num).toFixed(decimals) )  / n;
};

Dies betrifft auch den Beispielfall 1.005, der 1.01 zurückgibt.

4
momomo

Versuchen Sie, das jQuery . Number-Plug-In zu verwenden:

var number = 19.8000000007;
var res = 1 * $.number(number, 2);
4
user3447070

Zum Runden an Dezimalstellen pos (ohne Dezimalstellen) führen Sie Math.round(num * Math.pow(10,pos)) / Math.pow(10,pos) aus.

var console = {
 log: function(s) {
  document.getElementById("console").innerHTML += s + "<br/>"
 }
}
var roundDecimals=function(num,pos) {
 return (Math.round(num * Math.pow(10,pos)) / Math.pow(10,pos) );
}
//https://en.wikipedia.org/wiki/Pi
var pi=3.14159265358979323846264338327950288419716939937510;
for(var i=2;i<15;i++) console.log("pi="+roundDecimals(pi,i));
for(var i=15;i>=0;--i) console.log("pi="+roundDecimals(pi,i));
<div id="console" />
3
loretoparisi

Hier ist eine Funktion, die ich mir ausgedacht habe, um "aufzurunden". Ich habe double Math.round verwendet, um die ungenaue Multiplikation von JavaScript zu kompensieren, sodass 1.005 korrekt als 1.01 gerundet wird.

function myRound(number, decimalplaces){
    if(decimalplaces > 0){
        var multiply1 = Math.pow(10,(decimalplaces + 4));
        var divide1 = Math.pow(10, decimalplaces);
        return Math.round(Math.round(number * multiply1)/10000 )/divide1;
    }
    if(decimalplaces < 0){
        var divide2 = Math.pow(10, Math.abs(decimalplaces));
        var multiply2 = Math.pow(10, Math.abs(decimalplaces));
        return Math.round(Math.round(number / divide2) * multiply2);
    }
    return Math.round(number);
}
3
Andrei

Ich habe die folgenden Funktionen für mich geschrieben. Vielleicht hilft es Ihnen auch.

function float_exponent(number) {
    exponent = 1;
    while (number < 1.0) {
        exponent += 1
        number *= 10
    }
    return exponent;
}
function format_float(number, extra_precision) {
    precision = float_exponent(number) + (extra_precision || 0)
    return number.toFixed(precision).split(/\.?0+$/)[0]
}

Verwendungszweck:

format_float(1.01); // 1
format_float(1.06); // 1.1
format_float(0.126); // 0.13
format_float(0.000189); // 0.00019

Für Sie Fall:

format_float(10, 1); // 10
format_float(9.1, 1); // 9.1
format_float(1.77777, 1); // 1.78
3
vsvasya

Sie können auch die Funktion Math.round überschreiben, um die Rundung zu korrigieren und einen Parameter für Dezimalstellen hinzuzufügen. Verwenden Sie diesen Parameter wie folgt: Math.round (Number, Decimals). Beachten Sie, dass dies die eingebaute Komponente Math.round überschreibt und ihr eine andere Eigenschaft verleiht, als sie ursprünglich ist.

var round = Math.round;
Math.round = function (value, decimals) {
  decimals = decimals || 0;
  return Number(round(value + 'e' + decimals) + 'e-' + decimals);
}

Dann können Sie es einfach so verwenden:

Math.round(1.005, 2);

https://jsfiddle.net/k5tpq3pd/3/

3

Das hat für mich ganz gut geklappt, wenn ich immer auf eine bestimmte Dezimalstelle aufrunden wollte. Der Schlüssel hier ist, dass wir immer mit der Math.ceil-Funktion aufrunden werden.

Bei Bedarf können Sie Decke oder Boden unter bestimmten Bedingungen auswählen.

     /**
     * Possibility to lose precision at large numbers
     * @param number
     * @returns Number number
     */
    var roundUpToNearestHundredth = function(number) {

        // Ensure that we use high precision Number
        number = Number(number);

        // Save the original number so when we extract the Hundredth decimal place we don't bit switch or lose precision
        var numberSave = Number(number.toFixed(0));

        // Remove the "integer" values off the top of the number
        number = number - numberSave;

        // Get the Hundredth decimal places
        number *= 100;

        // Ceil the decimals.  Therefore .15000001 will equal .151, etc.
        number = Math.ceil(number);

        // Put the decimals back into their correct spot
        number /= 100;

        // Add the "integer" back onto the number
        return number + numberSave;

    };

console.log(roundUpToNearestHundredth(6132423.1200000000001))
2

Eine geringfügige Abweichung besteht darin, dass Sie einen Währungsbetrag entweder als ganzen Währungsbetrag oder als Betrag mit Bruchteilen der Währung formatieren müssen.

Zum Beispiel:

1 sollte $ 1 ausgeben

1.1 sollte $ 1.10 ausgeben

1,01 sollte 1,01 $ ausgeben

Angenommen, der Betrag ist eine Zahl:

const formatAmount = (amount) => amount % 1 === 0 ? amount : amount.toFixed(2);

Wenn amount keine Zahl ist, konvertieren Sie ihn mit parseFloat (amount) in eine Zahl.

2
Ibraheem

Aus den vorhandenen Antworten habe ich eine andere Lösung gefunden, die großartig zu funktionieren scheint, die auch mit dem Senden einer Zeichenfolge funktioniert und nachfolgende Nullen beseitigt.

function roundToDecimal(string, decimals) {
    return parseFloat(parseFloat(string).toFixed(decimals));
}

Es wird nicht berücksichtigt, wenn Sie einen Bullen einsenden ... wie "apa". Oder es wird wahrscheinlich einen Fehler auslösen, den ich sowieso für richtig halte. Es ist nie gut, Fehler zu verbergen, die behoben werden sollten (durch die aufrufende Funktion).

2
OZZIE

Ich habe festgestellt, dass dies für alle meine Anwendungsfälle funktioniert:

const round = (value, decimalPlaces = 0) => {
    const multiplier = Math.pow(10, decimalPlaces);
    return Math.round(value * multiplier + Number.EPSILON) / multiplier;
};

Denken Sie daran, dass dies ES6 ist. Ein ES5-Äquiv. wäre sehr einfach zu codieren, also werde ich es nicht hinzufügen.

1
Rob Evans

Ich wollte nur meinen Ansatz teilen, basierend auf den zuvor genannten Antworten:

Erstellen wir eine Funktion, die einen beliebigen numerischen Wert auf eine bestimmte Anzahl von Dezimalstellen rundet:

function roundWDecimals(n, decimals) {
    if (!isNaN(parseFloat(n)) && isFinite(n)) {
        if (typeof(decimals) == typeof(undefined)) {
            decimals = 0;
        }
        var decimalPower = Math.pow(10, decimals);
        return Math.round(parseFloat(n) * decimalPower) / decimalPower;
    }
    return NaN;
}

Und führen Sie eine neue "runde" Methode für den Zahlenprototyp ein:

Object.defineProperty(Number.prototype, 'round', {
    enumerable: false,
    value: function(decimals) {
        return roundWDecimals(this, decimals);
    }
});

Und Sie können es testen:

function roundWDecimals(n, decimals) {
    if (!isNaN(parseFloat(n)) && isFinite(n)) {
        if (typeof(decimals) == typeof(undefined)) {
            decimals = 0;
        }
        var decimalPower = Math.pow(10, decimals);
        return Math.round(parseFloat(n) * decimalPower) / decimalPower;
    }
    return NaN;
}
Object.defineProperty(Number.prototype, 'round', {
    enumerable: false,
    value: function(decimals) {
        return roundWDecimals(this, decimals);
    }
});

var roundables = [
    {num: 10, decimals: 2},
    {num: 1.7777777, decimals: 2},
    {num: 9.1, decimals: 2},
    {num: 55.55, decimals: 1},
    {num: 55.549, decimals: 1},
    {num: 55, decimals: 0},
    {num: 54.9, decimals: 0},
    {num: -55.55, decimals: 1},
    {num: -55.551, decimals: 1},
    {num: -55, decimals: 0},
    {num: 1.005, decimals: 2},
    {num: 1.005, decimals: 2},
    {num: 19.8000000007, decimals: 2},
  ],
  table = '<table border="1"><tr><th>Num</th><th>Decimals</th><th>Result</th></tr>';
$.each(roundables, function() {
  table +=
    '<tr>'+
      '<td>'+this.num+'</td>'+
      '<td>'+this.decimals+'</td>'+
      '<td>'+this.num.round(this.decimals)+'</td>'+
    '</tr>'
  ;
});
table += '</table>';
$('.results').append(table);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="results"></div>
1
Deele

Hier ist meine Lösung für dieses Problem:

function roundNumber(number, precision = 0) {
var num = number.toString().replace(",", "");
var integer, decimal, significantDigit;

if (num.indexOf(".") > 0 && num.substring(num.indexOf(".") + 1).length > precision && precision > 0) {
    integer = parseInt(num).toString();
    decimal = num.substring(num.indexOf(".") + 1);
    significantDigit = Number(decimal.substr(precision, 1));

    if (significantDigit >= 5) {
        decimal = (Number(decimal.substr(0, precision)) + 1).toString();
        return integer + "." + decimal;
    } else {
        decimal = (Number(decimal.substr(0, precision)) + 1).toString();
        return integer + "." + decimal;
    }
}
else if (num.indexOf(".") > 0) {
    integer = parseInt(num).toString();
    decimal = num.substring(num.indexOf(".") + 1);
    significantDigit = num.substring(num.length - 1, 1);

    if (significantDigit >= 5) {
        decimal = (Number(decimal) + 1).toString();
        return integer + "." + decimal;
    } else {            
        return integer + "." + decimal;
    }
} 

return number;
}
1
caliche2000

die frage ist nach runden von 2 dezimalstellen.

lassen Sie uns nicht diese komplizierte modifizierende Prototypkette usw. machen.

hier ist eine einzeilige Lösung

let round2dec = num => Math.round(num * 100) / 100; 

console.log(round2dec(1.77));
console.log(round2dec(1.774));
console.log(round2dec(1.777));
console.log(round2dec(10));
1
Salman

Nur für den Datensatz könnte die Skalierungsmethode theoretisch Unendlich zurückgeben, wenn die Zahl und die Stellen, auf die gerundet werden soll, groß genug sind. In JavaScript sollte dies kein Problem sein, da die maximale Anzahl 1.7976931348623157e + 308 ist. Wenn Sie jedoch mit sehr großen Zahlen oder vielen Dezimalstellen arbeiten, können Sie stattdessen diese Funktion ausprobieren:

Number.prototype.roundTo = function(digits)
{
    var str = this.toString();
    var split = this.toString().split('e');
    var scientific = split.length > 1;
    var index;
    if (scientific)
    {
        str = split[0];
        var decimal = str.split('.');
        if (decimal.length < 2)
            return this;
        index = decimal[0].length + 1 + digits;
    }
    else
        index = Math.floor(this).toString().length + 1 + digits;
    if (str.length <= index)
        return this;
    var digit = str[index + 1];
    var num = Number.parseFloat(str.substring(0, index));
    if (digit >= 5)
    {
        var extra = Math.pow(10, -digits);
        return this < 0 ? num - extra : num + extra;
    }
    if (scientific)
        num += "e" + split[1];
    return num;
}
1
Martin

Die große Herausforderung bei dieser scheinbar einfachen Aufgabe besteht darin, dass sie psychologisch erwartete Ergebnisse liefern soll, auch wenn die Eingabe zunächst nur minimale Rundungsfehler enthält (ganz zu schweigen von den Fehlern, die in unserer Berechnung auftreten werden). Wenn wir wissen, dass das reale Ergebnis genau 1.005 ist, erwarten wir, dass das Runden auf zwei Stellen 1.01 ergibt, auch wenn 1.005 das Ergebnis einer umfangreichen Berechnung mit vielen Rundungsfehlern auf dem Weg ist.

Das Problem wird noch offensichtlicher, wenn es sich um floor() anstatt um round() handelt. Wenn Sie zum Beispiel nach den letzten beiden Ziffern hinter dem Punkt 33.3 alles wegschneiden, würden wir sicher erwarten, dass nicht 33.29 als Ergebnis erhalten, aber das ist, was passiert:

console.log(Math.floor(33.3 * 100) / 100)

In einfachen Fällen besteht die Lösung darin, eine Berechnung mit Zeichenfolgen anstelle von Gleitkommazahlen durchzuführen und so Rundungsfehler vollständig zu vermeiden. Diese Option schlägt jedoch bei der ersten nicht trivialen mathematischen Operation (einschließlich der meisten Divisionen) fehl und ist langsam.

Wenn Sie mit Gleitkommazahlen arbeiten, besteht die Lösung darin, einen Parameter einzuführen, der den Betrag angibt, um den wir bereit sind, vom tatsächlichen Berechnungsergebnis abzuweichen, um das psychologisch erwartete Ergebnis auszugeben.

var round = function(num, digits = 2, compensateErrors = 2) {
  if (num < 0) {
    return -this.round(-num, digits, compensateErrors);
  }
  const pow = Math.pow(10, digits);
  return (Math.round(num * pow * (1 + compensateErrors * Number.EPSILON)) / pow);
}

/* --- testing --- */

console.log("Edge cases mentioned in this thread:")
var values = [ 0.015, 1.005, 5.555, 156893.145, 362.42499999999995, 1.275, 1.27499, 1.2345678e+2, 2.175, 5.015, 58.9 * 0.15 ];
values.forEach((n) => {
  console.log(n + " -> " + round(n));
  console.log(-n + " -> " + round(-n));
});

console.log("\nFor numbers which are so large that rounding cannot be performed anyway within computation precision, only string-based computation can help.")
console.log("Standard: " + round(1e+19));
console.log("Compensation = 1: " + round(1e+19, 2, 1));
console.log("Effectively no compensation: " + round(1e+19, 2, 0.4));

Hinweis: Internet Explorer kennt Number.EPSILON nicht. Wenn Sie sich in der unglücklichen Lage befinden, es weiterhin unterstützen zu müssen, können Sie ein Shim verwenden oder einfach die Konstante für diese bestimmte Browserfamilie selbst definieren.

1
malamut

Das Rundungsproblem kann vermieden werden, indem Zahlen in Exponentialschreibweise verwendet werden.

public roundFinancial(amount: number, decimals: number) {
    return Number(Math.round(Number(`${amount}e${decimals}`)) + `e-${decimals}`);
}
1
Dmytro Medvid

In der Node-Umgebung benutze ich einfach das roundTo Modul:

const roundTo = require('round-to');
...
roundTo(123.4567, 2);

// 123.46
1
Simon Prickett

Bei dieser Antwort geht es mehr um Geschwindigkeit.

var precalculatedPrecisions = [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10];

function round(num, _prec) {
    _precision = precalculatedPrecisions[_prec]
    return Math.round(num * _precision + 1e-14) / _precision ;
}

jsPerf darüber.

1
aleha

Eine generische Antwort für alle Browser und Präzisionen:

function round(num, places) {
      if(!places){
       return Math.round(num);
      }

      var val = Math.pow(10, places);
      return Math.round(num * val) / val;
}

round(num, 2);
1
RBZ

Ausgehend von dem vorgeschlagenen Beispiel über precisionRound , das ich am MDN (diesem Ereignis) gefunden habe Für 1.005 Retouren 1 und nicht 1.01) schreibe ich eine benutzerdefinierte precisionRound , die eine zufällige Genauigkeitszahl verwaltet, und für 1.005 wird 1.01 zurückgegeben.

Dies ist die Funktion:

function precisionRound(number, precision)
{
  if(precision < 0)
  {
    var factor = Math.pow(10, precision);
    return Math.round(number * factor) / factor;
  }
  else
    return +(Math.round(number + "e+"+precision)  + "e-"+precision);
}

console.log(precisionRound(1234.5678, 1));  // output: 1234.6
console.log(precisionRound(1234.5678, -1)); // output: 1230
console.log(precisionRound(1.005, 2));      // output: 1.01
console.log(precisionRound(1.0005, 2));     // output: 1
console.log(precisionRound(1.0005, 3));     // output: 1.001
console.log(precisionRound(1.0005, 4));     // output: 1.0005

Für TypeScript:

public static precisionRound(number: number, precision: number)
{
  if (precision < 0)
  {
    let factor = Math.pow(10, precision);
    return Math.round(number * factor) / factor;
  }
  else
    return +(Math.round(Number(number + "e+" + precision)) +
      "e-" + precision);
}
1
Marco Barbero

Node.js

Dies erledigte den Trick für mich auf Node.js in Sekundenschnelle:

npm install math

Quelle: http://mathjs.org/examples/basic_usage.js.html

0
nottinhill

Bitte nutzen Sie die unten stehende Funktion, wenn Sie nicht abrunden möchten.

function ConvertToDecimal(num) {
  num = num.toString(); // If it's not already a String
  num = num.slice(0, (num.indexOf(".")) + 3); // With 3 exposing the hundredths place    
alert('M : ' + Number(num)); // If you need it back as a Number     
}
0
Nimesh
number=(parseInt((number +0.005)*100))/100;     

addiere 0.005 wenn du eine normale Runde machen willst (2 Dezimalstellen)

8.123 +0.005=> 8.128*100=>812/100=>8.12   

8.126 +0.005=> 8.131*100=>813/100=>8.13   
0
Elid Garazlic

Ich habe diese Funktion erstellt, um eine Zahl zu runden. Der Wert kann eine Zeichenfolge sein (z. B. '1.005') oder eine Zahl von 1.005, die standardmäßig 1 ist. Wenn Sie als Dezimalzahl 2 angeben, lautet das Ergebnis 1.01

round(value: string | number, decimals: number | string = "0"): number | null {
    return +( Math.round(Number(value + "e+"+decimals)) + "e-" + decimals);
}

Verwendung: rund (1,005, 2) // 1,01 oder Verwendung: rund (1,005, 2) // 1,01

0
chriscrossweb

Verwenden der Lösung von Brian Ustas:

function roundDecimal(value, precision) {
    var multiplier = Math.pow(10, precision);
    return Math.round(value * multiplier) / multiplier;
}
0
Roman M

Schnellhilfe-Funktion mit rounging Standardrundung: Rundung lassen = 4;

let round=(number)=>{ let multiply=Math.pow(10,rounding);  return Math.round(number*multiply)/multiply};

console.log(round(0.040579431));

=> 0,0406