Unbedeutende nachgestellte Nullen aus einer Zahl entfernen?

157

Habe ich einen Standard-API-Aufruf verpasst, bei dem nachfolgende unbedeutende Nullen aus einer Zahl entfernt werden?

Ex.

var x = 1.234000 // to become 1.234;
var y = 1.234001; // stays 1.234001

Number.toFixed () und Number.toPrecision () sind nicht ganz das, wonach ich suche.

Steven
quelle
6
Ähm , 1.234000 === 1.234.
Gumbo
5
Ja, wenn Sie Alarm (x) machen, erscheint es ohne die nachgestellten Nullen
JKirchartz
50
Nachdem ich mit einer Reihe von Clients gearbeitet habe, kann ich bezeugen, dass Clients, obwohl 1.234000 === 1.234, diese zusätzlichen Nullen nicht sehen möchten, wenn sie dies nicht müssen.
Kontaktmatt
16
Verwenden parseFloat(n)?
Herr Alien
Dies war für mich die einfachste Lösung, die alle Randfälle abdeckte, danke @ Mr.Alien.
James Perih

Antworten:

140

Wenn Sie es in eine Zeichenfolge konvertieren, werden keine nachgestellten Nullen angezeigt, die nicht in der Variablen gespeichert sind, seit sie als Zahl und nicht als Zeichenfolge erstellt wurden.

var n = 1.245000
var noZeroes = n.toString() // "1.245" 
Cristian Sanchez
quelle
6
Ich wollte gerade Code posten, um die Nullen zu entfernen, aber Daniels Lösung scheint zu funktionieren. Es funktioniert sogar für Strings wie "1.2345000". ("1.2345000" * 1) .toString (); // wird 1.2345
Steven
7
Wenn Ihre
Variable
Das hat super geklappt. Ich hatte das gleiche Problem, konvertierte float in string und parseFloat, um es wieder in das richtige Format zu bringen, nur ohne die nachgestellten Nullen.
Matt West
10
Dies ist keine vollständige Lösung. Es funktioniert nicht, wenn Sie Variable mit etwas Gleitkommadarstellung Fehler haben, wie: var n = 1.245000000000001(vorausgesetzt , es unbedeutend ist, Benutzer dargestellt werden)
Augur
7
Kann zu unerwarteten Ergebnissen für Zahlen wie: 123111111111111111111111111111122222222222222222222222222222222222222222222222222. Die Zeichenfolgendarstellung wird im Exponentialformat sein: 1.231111111111111e + 81
Stas Makutin
226

Ich hatte eine ähnliche Instanz, in der ich sie .toFixed()bei Bedarf verwenden wollte, aber ich wollte die Polsterung nicht, wenn sie nicht vorhanden war. Also habe ich parseFloat in Verbindung mit toFixed verwendet.

toFixed ohne Polsterung

parseFloat(n.toFixed(4));

Eine weitere Option, die fast dasselbe tut.
Diese Antwort kann Ihnen bei Ihrer Entscheidung helfen

Number(n.toFixed(4));

toFixedrundet / füllt die Zahl auf eine bestimmte Länge, konvertiert sie aber auch in eine Zeichenfolge. Wenn Sie dies wieder in einen numerischen Typ konvertieren, wird die arithmetische Verwendung der Zahl nicht nur sicherer, sondern es werden auch automatisch nachfolgende Nullen gelöscht. Beispielsweise:

var n = "1.234000";
    n = parseFloat(n);
 // n is 1.234 and in number form

Denn selbst wenn Sie eine Zahl mit nachgestellten Nullen definieren, werden sie gelöscht.

var n = 1.23000;
 // n == 1.23;
Gary
quelle
Beachten Sie, dass dies nur funktioniert, wenn die relevante Anzahl von Dezimalstellen gleich oder größer als das Argument toFixed ist. Wenn die Zahl beispielsweise 1.200000 ist, ist das Ergebnis von toFixed (3) 1.200, und daher werden nicht alle nachfolgenden Nullen entfernt.
Leopoldo Sanczyk
@LeopoldoSanczyk Nein, das stimmt nur, wenn Sie nur toFixed verwenden, da es eine Zeichenfolge zurückgibt. Zahlentypen verlieren automatisch nachgestellte Nullen. Deshalb habe ich die beiden zusammen verwendet.
Gary
@ Gary, ich ziehe meinen Kommentar zurück, ich habe parseFloat(n).toFixed(4);anstelle Ihrer eigentlichen Antwort gesehen. Es tut mir Leid.
Leopoldo Sanczyk
2
Warum nicht +(n.toFixed(4))?
Константин Ван
3
upvoted! Nur ein Problem mit Ihrer Antwort 0.00000005 wird in 5e-8 konvertiert. Wie kann ich unbedeutende Nullen ohne dieses Problem entfernen? Ich arbeite mit kleinen Zahlen wie 0.000058000, bei denen Nullen am Ende entfernt werden müssen
PirateApp
29

Ich habe zuerst eine Kombination aus Matti-Lyra und Garys Antworten verwendet:

r=(+n).toFixed(4).replace(/\.0+$/,'')

Ergebnisse:

  • 1234870.98762341: 1234870.9876
  • 1230009100: "1230009100"
  • 0,0012234: 0,0012
  • 0,1200234: 0,12
  • 0,000001231: "0"
  • 0,10001: 0,1000
  • "asdf": "NaN" (also kein Laufzeitfehler)

Der etwas problematische Fall ist 0.10001. Am Ende habe ich diese längere Version verwendet:

    r = (+n).toFixed(4);
    if (r.match(/\./)) {
      r = r.replace(/\.?0+$/, '');
    }
  • 1234870.98762341: 1234870.9876
  • 1230009100: "1230009100"
  • 0,0012234: 0,0012
  • 0,1200234: 0,12
  • 0,000001231: "0"
  • 0,10001: 0,1
  • "asdf": "NaN" (also kein Laufzeitfehler)

Update : Und dies ist Garys neuere Version (siehe Kommentare):

r=(+n).toFixed(4).replace(/([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/,'$1')

Dies ergibt die gleichen Ergebnisse wie oben.

w00t
quelle
1
Ich habe eine reine Regex-Lösung, von der ich glaube, dass sie funktionierttoFixed(4).replace(/([0-9]+(\.[1-9]+)?)(\.?0+$)/,"$1")
Gary
1
Gah! Anscheinend bin ich bei weitem nicht so gut darin, meine eigenen RegExes zu brechen als andere. Ich werde mich davon nicht schlagen lassen! Ich habe diesen Test gegen alle Ihre Testfälle und alle (gültigen) Tests durchgeführt, die mir ([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)
Gary
1
Der reguläre Ausdruck ist zu gierig und entfernt manchmal eine "0" aus dem ganzzahligen Teil! :-( Warum nicht einfach replace(/[,.][1-9]+(0+)/,'')?
Sebastian Sebald
1
Unterschätzte Antwort darauf.
Charlie
1
@ w00t Oh, sorry, ich verstehe jetzt. Ich war die Art und Weise, wie ich meine getestet habe (siehe Link oben). Ihre Funktion schlägt nicht fehl, wenn Sie toFixed verwenden, da die Zahl garantiert einen Punkt enthält. In meinen Tests ist sie jedoch fehlgeschlagen, da ich wollte, dass der reguläre Ausdruck für eine beliebige Zahl funktioniert, einschließlich Ganzzahlen ohne Punkt. Ohne toFixed isst es am Ende eine Null. Mein Fehler.
Geekley
21

Die toFixedMethode führt bei Bedarf die entsprechende Rundung durch. Es werden auch nachgestellte Nullen hinzugefügt, was nicht immer ideal ist.

(4.55555).toFixed(2);
//-> "4.56"

(4).toFixed(2);
//-> "4.00"

Wenn Sie den Rückgabewert in eine Zahl umwandeln, werden diese nachgestellten Nullen gelöscht. Dies ist ein einfacherer Ansatz als Ihre eigene Rundungs- oder Kürzungsmathematik.

+(4.55555).toFixed(2);
//-> 4.56

+(4).toFixed(2);
//-> 4
CJ
quelle
1
knifflig, aber genau das, wonach ich gesucht habe: Entfernen von signifikanten nachgestellten Nullen (was wir natürlich durch den toFixedAufruf signifikant gemacht haben ). Es ist ein seltsamer UX Edge-Fall.
Worc
12

Ich hatte im Grunde die gleiche Anforderung und stellte fest, dass es für diese Funktionalität keinen eingebauten Mechanismus gibt.

Zusätzlich zum Trimmen der nachfolgenden Nullen musste ich auch die Ausgabe für das aktuelle Gebietsschema des Benutzers (dh 123.456.789) abrunden und formatieren.

Alle meine Arbeiten dazu wurden als prettyFloat.js (MIT Licensed) auf GitHub aufgenommen: https://github.com/dperish/prettyFloat.js


Anwendungsbeispiele:

prettyFloat(1.111001, 3) // "1.111"
prettyFloat(1.111001, 4) // "1.111"
prettyFloat(1.1111001, 5) // "1.1111"
prettyFloat(1234.5678, 2) // "1234.57"
prettyFloat(1234.5678, 2, true) // "1,234.57" (en-us)


Aktualisiert - August 2018


Alle modernen Browser unterstützen jetzt die ECMAScript Internationalization API , die sprachempfindlichen Zeichenfolgenvergleich, Zahlenformatierung sowie Datums- und Uhrzeitformatierung bietet.

let formatters = {
    default: new Intl.NumberFormat(),
    currency: new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', minimumFractionDigits: 0, maximumFractionDigits: 0 }),
    whole: new Intl.NumberFormat('en-US', { style: 'decimal', minimumFractionDigits: 0, maximumFractionDigits: 0 }),
    oneDecimal: new Intl.NumberFormat('en-US', { style: 'decimal', minimumFractionDigits: 1, maximumFractionDigits: 1 }),
    twoDecimal: new Intl.NumberFormat('en-US', { style: 'decimal', minimumFractionDigits: 2, maximumFractionDigits: 2 })
};

formatters.twoDecimal.format(1234.5678);  // result: "1,234.57"
formatters.currency.format(28761232.291); // result: "$28,761,232"

Für ältere Browser können Sie diese Polyfüllung verwenden: https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.en

dperish
quelle
Das haben wir gesucht. Sie müssen ein npm-Paket erstellen.
EnZo
Daher sollte ich dies wahrscheinlich aktualisieren, da dies jetzt über die Internationalisierungs-API möglich ist.
Dperish
2
Dies ist sehr hilfreich, danke für das Teilen und danke auch für das Update.
Jaggedsoft
11

Wie wäre es einfach mit einem solchen zu multiplizieren?

var x = 1.234000*1; // becomes 1.234

var y = 1.234001*1; // stays as 1.234001
Howard
quelle
9

Sie können dies versuchen, um schwebende Zahlen zu minimieren

var n = 0.0000;
n = parseFloat(n.toString()); 

//output n = 0; 
// n = 3.14000; --> n = 3.14;
Amit Panasara
quelle
7

Reine Regex-Antwort

n.replace(/(\.[0-9]*[1-9])0+$|\.0*$/,'$1');

Ich frage mich, warum niemand einen gegeben hat!

João Costa
quelle
Es funktioniert nicht mit Zahlen (Zahlen sind in der ursprünglichen Frage angegeben). Ich liebe die Lösung für eine String-Darstellung!
BennyHilarious
6

Ich musste dieses Problem auch lösen, als Django Werte vom Typ Dezimal in einem Textfeld anzeigte. ZB wenn '1' der Wert war. Es würde '1.00000000' anzeigen. Wenn '1.23' der Wert wäre, würde '1.23000000' angezeigt (im Fall einer Einstellung von 'decimal_places' von 8)

Die Verwendung von parseFloat war für mich keine Option, da möglicherweise nicht genau derselbe Wert zurückgegeben wird. toFixed war keine Option, da ich nichts runden wollte, also habe ich eine Funktion erstellt:

function removeTrailingZeros(value) {
    value = value.toString();

    # if not containing a dot, we do not need to do anything
    if (value.indexOf('.') === -1) {
        return value;
    }

    # as long as the last character is a 0 or a dot, remove it
    while((value.slice(-1) === '0' || value.slice(-1) === '.') && value.indexOf('.') !== -1) {
        value = value.substr(0, value.length - 1);
    }
    return value;
}
Megasnort
quelle
Dies funktioniert, ist jedoch recht ineffizient, da pro Ausführung mehrere Zeichenfolgen erstellt werden. Stellen Sie sich vor, Sie führen dies für alle Zellen in einer Tabelle aus, in der eine gute Zahl 0,00000 betrug. Eine bessere Option wäre, zu bestimmen, wie viele nachgestellte Nullen vorhanden sind, und dann das Slice auf einmal auszuführen. Das Bestimmen, was ein Zeichen ist, ist weitgehend effizient, das Aufteilen von Zeichenfolgen ist weniger effizient.
Derek Nigel Bartram
Ich habe etwas Ähnliches getan wie Ihr Vorschlag Derek: github.com/rek/remove-trailing-zeros/blob/master/…
rekarnar
Der Perf-Test ist da: jsperf.com/remove-trailing-zeros/1 , Sie hatten Recht, die Nullen zu finden und zu entfernen ist viel schneller!
Rekarnar
4

Keine dieser Lösungen hat bei mir für sehr kleine Stückzahlen funktioniert. http://numeraljs.com/ hat das für mich gelöst.

parseFloat(0.00000001.toFixed(8));
// 1e-8

numeral(0.00000001).format('0[.][00000000]');
// "0.00000001"
Devon
quelle
Es kann nicht mehr als 6 Präzision verarbeiten. Ich würde sagen, diese Bibliothek ist nutzlos, wenn sie für kleine Zahlen gedacht ist. Auf keinen Fall zu empfehlen.
Daniel Kmak
2

Wenn Sie Floats aus irgendeinem Grund nicht verwenden können (z. B. bei Geld-Floats) und bereits von einer Zeichenfolge ausgehen, die eine korrekte Zahl darstellt, ist diese Lösung möglicherweise hilfreich. Es konvertiert eine Zeichenfolge, die eine Zahl darstellt, in eine Zeichenfolge, die eine Zahl ohne nachgestellte Nullen darstellt.

function removeTrailingZeroes( strAmount ) {
    // remove all trailing zeroes in the decimal part
    var strDecSepCd = '.'; // decimal separator
    var iDSPosition = strAmount.indexOf( strDecSepCd ); // decimal separator positions
    if ( iDSPosition !== -1 ) {
        var strDecPart = strAmount.substr( iDSPosition ); // including the decimal separator

        var i = strDecPart.length - 1;
        for ( ; i >= 0 ; i-- ) {
            if ( strDecPart.charAt(i) !== '0') {
                break;
            }
        }

        if ( i=== 0 ) {
            return strAmount.substring(0, iDSPosition);
        } else {
            // return INTPART and DS + DECPART including the rightmost significant number
            return strAmount.substring(0, iDSPosition) + strDecPart.substring(0,i + 1);
        }
    }

    return strAmount;
}
BennyHilarious
quelle
0

Nachdem ich alle Antworten - und Kommentare - gelesen hatte, kam ich zu folgendem Ergebnis:

function isFloat(n) {
    let number = (Number(n) === n && n % 1 !== 0) ? eval(parseFloat(n)) : n;
    return number;
}

Ich weiß mit eval irgendwie schädlich sein kann, aber das hat mir sehr geholfen.

So:

isFloat(1.234000);     // = 1.234;
isFloat(1.234001);     // = 1.234001
isFloat(1.2340010000); // = 1.234001

Wenn Sie die Dezimalstellen begrenzen möchten, verwenden Sie, toFixed()wie in anderen angegeben.

let number = (Number(n) === n && n % 1 !== 0) ? eval(parseFloat(n).toFixed(3)) : n;

Das ist es.

ed1nh0
quelle
0

Ich musste alle nachgestellten Nullen entfernen, aber mindestens 2 Dezimalstellen, einschließlich aller Nullen , beibehalten.
Die Zahlen, mit denen ich arbeite, sind 6 Dezimalzahlen, die von .toFixed (6) generiert werden.

Erwartetes Ergebnis:

var numstra = 12345.000010 // should return 12345.00001
var numstrb = 12345.100000 // should return 12345.10
var numstrc = 12345.000000 // should return 12345.00
var numstrd = 12345.123000 // should return 12345.123

Lösung:

var numstr = 12345.100000

while (numstr[numstr.length-1] === "0") {           
    numstr = numstr.slice(0, -1)
    if (numstr[numstr.length-1] !== "0") {break;}
    if (numstr[numstr.length-3] === ".") {break;}
}

console.log(numstr) // 12345.10

Logik:

Führen Sie die Schleifenfunktion aus, wenn das letzte Zeichen der Zeichenfolge eine Null ist.
Entfernen Sie das letzte Zeichen und aktualisieren Sie die Zeichenfolgenvariable.
Wenn das letzte Zeichen der aktualisierten Zeichenfolge keine Null ist, beenden Sie die Schleife.
Wenn die aktualisierte Zeichenfolge des vorletzten Zeichens eine Gleitkomma-Endschleife ist.

Kevin H.
quelle
-1

Hier ist eine mögliche Lösung:

var x = 1.234000 // to become 1.234;
var y = 1.234001; // stays 1.234001

eval(x) --> 1.234
eval(y) --> 1.234001
Mond
quelle
4
Für diese einfache Aufgabe brauchen Sie keine Bewertung! parseFloat()wird sehr angemessen sein.
Hutchbat
6
eval == böse. Verwenden Sie es nie
eagor
-2

Nur eine einfache mathematische Alternative zur Verwendung toFixed

function truncateNumber( num, precision ){
    let c = Math.pow(10,precision);
    return Math.trunc( Math.round(num*c) )/c;
}
    
console.log( truncateNumber(1234.5678, 3) );
console.log( truncateNumber(1234.56, 3) );

Gary
quelle