J'essaye de tronquer les nombres décimaux en décimales. Quelque chose comme ça:
5.467 -> 5.46
985.943 -> 985.94
toFixed(2)
fait à peu près ce qu'il faut mais arrondit la valeur. Je n'ai pas besoin d'arrondir la valeur. J'espère que cela est possible en javascript.
Réponses:
upd :
Donc, après tout, il s'est avéré que les bugs arrondis vous hanteront toujours, peu importe à quel point vous essayez de les compenser. Par conséquent, le problème doit être attaqué en représentant les nombres exactement en notation décimale.
Number.prototype.toFixedDown = function(digits) { var re = new RegExp("(\\d+\\.\\d{" + digits + "})(\\d)"), m = this.toString().match(re); return m ? parseFloat(m[1]) : this.valueOf(); }; [ 5.467.toFixedDown(2), 985.943.toFixedDown(2), 17.56.toFixedDown(2), (0).toFixedDown(1), 1.11.toFixedDown(1) + 22]; // [5.46, 985.94, 17.56, 0, 23.1]
Ancienne solution sujette aux erreurs basée sur la compilation des autres:
Number.prototype.toFixedDown = function(digits) { var n = this - Math.pow(10, -digits)/2; n += n / Math.pow(2, 53); // added 1360765523: 17.56.toFixedDown(2) === "17.56" return n.toFixed(digits); }
la source
1.11.toFixedDown(1) + 22
se termine comme1.122
au lieu de23.1
. Devrait aussi0.toFixedDown(1)
produire0
mais à la place il produit-0.1
.(-10.2131).toFixedDown(2) // ==> 10.21
.(1e-7).toFixedDown(0) // ==> 1e-7
. Est - ce que pour1e-(>=7)
(ex:1e-8
,1e-9
, ...).La réponse de Dogbert est bonne, mais si votre code doit gérer des nombres négatifs, il
Math.floor
peut à lui seul donner des résultats inattendus.Par exemple
Math.floor(4.3) = 4
, maisMath.floor(-4.3) = -5
Utilisez plutôt une fonction d'aide comme celle-ci pour obtenir des résultats cohérents:
truncateDecimals = function (number) { return Math[number < 0 ? 'ceil' : 'floor'](number); }; // Applied to Dogbert's answer: var a = 5.467; var truncated = truncateDecimals(a * 100) / 100; // = 5.46
Voici une version plus pratique de cette fonction:
truncateDecimals = function (number, digits) { var multiplier = Math.pow(10, digits), adjustedNum = number * multiplier, truncatedNum = Math[adjustedNum < 0 ? 'ceil' : 'floor'](adjustedNum); return truncatedNum / multiplier; }; // Usage: var a = 5.467; var truncated = truncateDecimals(a, 2); // = 5.46 // Negative digits: var b = 4235.24; var truncated = truncateDecimals(b, -2); // = 4200
Si ce n'est pas le comportement souhaité, insérez un appel à
Math.abs
sur la première ligne:var multiplier = Math.pow(10, Math.abs(digits)),
EDIT: shendz souligne correctement que l'utilisation de cette solution avec
a = 17.56
produira incorrectement17.55
. Pour en savoir plus sur les raisons de cette situation, lisez Ce que tout informaticien devrait savoir sur l'arithmétique à virgule flottante . Malheureusement, écrire une solution qui élimine toutes les sources d'erreur en virgule flottante est assez délicat avec javascript. Dans une autre langue, vous utiliseriez des entiers ou peut-être un type décimal, mais avec javascript ...Cette solution doit être précise à 100%, mais elle sera également plus lente:
function truncateDecimals (num, digits) { var numS = num.toString(), decPos = numS.indexOf('.'), substrLength = decPos == -1 ? numS.length : 1 + decPos + digits, trimmedResult = numS.substr(0, substrLength), finalResult = isNaN(trimmedResult) ? 0 : trimmedResult; return parseFloat(finalResult); }
Pour ceux qui ont besoin de vitesse mais qui veulent également éviter les erreurs en virgule flottante, essayez quelque chose comme BigDecimal.js . Vous pouvez trouver d'autres bibliothèques javascript BigDecimal dans cette question SO: "Existe-t-il une bonne bibliothèque Javascript BigDecimal?" et voici un bon article de blog sur les bibliothèques mathématiques pour Javascript
la source
if(isNAN(result) result = 0;
dépend du comportement souhaité.var a = 5.467; var truncated = Math.floor(a * 100) / 100; // = 5.46
la source
truncate(-3.14)
et reçois en-4
retour, j'appellerais certainement cela indésirable.var a = 65.1
var truncated = Math.floor(a * 100) / 100; // = 65.09
Par conséquent, ce n'est pas une solution correcteVous pouvez corriger l'arrondi en soustrayant 0,5 pour toFixed, par exemple
(f - 0.005).toFixed(2)
la source
Pensez à tirer profit de la double tilde:
~~
.Prenez le nombre. Multipliez par les chiffres significatifs après la décimale afin de pouvoir tronquer à zéro place avec
~~
. Divisez ce multiplicateur. Profit.function truncator(numToTruncate, intDecimalPlaces) { var numPower = Math.pow(10, intDecimalPlaces); // "numPowerConverter" might be better return ~~(numToTruncate * numPower)/numPower; }
J'essaye de résister à envelopper l'
~~
appel dans des parens; l'ordre des opérations devrait faire en sorte que cela fonctionne correctement, je crois.alert(truncator(5.1231231, 1)); // is 5.1
alert(truncator(-5.73, 1)); // is -5.7
alert(truncator(-5.73, 0)); // is -5
Lien JSFiddle .
EDIT: Avec le recul, j'ai involontairement traité des cas pour arrondir également la gauche de la décimale.
alert(truncator(4343.123, -2)); // gives 4300.
La logique est un peu farfelue à la recherche de cet usage et peut bénéficier d'une refactorisation rapide. Mais ça marche toujours. Mieux vaut avoir de la chance que du bien.
la source
Math
prototype avec ceci et vérifiez les NaN-s avant de l'exécuter, ce serait tout simplement parfait.truncator((10 * 2.9) / 100, 2)
return 0.28 au lieu de 0.29 ... jsfiddle.net/25tgrzq1Belle solution en une ligne:
function truncate (num, places) { return Math.trunc(num * Math.pow(10, places)) / Math.pow(10, places); }
Alors appelez-le avec:
truncate(3.5636232, 2); // returns 3.56 truncate(5.4332312, 3); // returns 5.433 truncate(25.463214, 4); // returns 25.4632
la source
J'ai pensé ajouter une réponse en utilisant
|
car il est simple et fonctionne bien.truncate = function(number, places) { var shift = Math.pow(10, places); return ((number * shift) | 0) / shift; };
la source
or
ing avec 0 signifie "juste garder ce que j'ai déjà". Fait ce que ma~~
réponse fait, mais avec une seule opération au niveau du bit. Bien qu'il ait la même limitation que celle écrite aussi: nous ne pouvons pas dépasser 2 ^ 31 .truncate((10 * 2.9) / 100);
ce code renvoie 0,28 au lieu de 0,29 jsfiddle.net/9pf0732dTronquer à l'aide d'opérateurs au niveau du bit:
~~0.5 === 0 ~~(-0.5) === 0 ~~14.32794823 === 14 ~~(-439.93) === -439
la source
La réponse de @ Dogbert peut être améliorée avec
Math.trunc
, qui tronque au lieu d'arrondir.var a = 5.467; var truncated = Math.trunc(a * 100) / 100; // = 5.46
var a = -5.467; var truncated = Math.trunc(a * 100) / 100; // = -5.46
la source
Math.trunc
, mais plutôt que9.28 * 100
est927.9999
plutôt que928
. Vous voudrez peut-être lire les dangers de laJ'ai écrit une réponse en utilisant une méthode plus courte. Voici ce que j'ai trouvé
function truncate(value, precision) { var step = Math.pow(10, precision || 0); var temp = Math.trunc(step * value); return temp / step; }
La méthode peut être utilisée comme ça
truncate(132456.25456789, 5)); // Output: 132456.25456 truncate(132456.25456789, 3)); // Output: 132456.254 truncate(132456.25456789, 1)); // Output: 132456.2 truncate(132456.25456789)); // Output: 132456
Ou, si vous voulez une syntaxe plus courte, c'est parti
function truncate(v, p) { var s = Math.pow(10, p || 0); return Math.trunc(s * v) / s; }
la source
Number.prototype.trim = function(decimals) { var s = this.toString(); var d = s.split("."); d[1] = d[1].substring(0, decimals); return parseFloat(d.join(".")); } console.log((5.676).trim(2)); //logs 5.67
la source
Je pense que cette fonction pourrait être une solution simple:
function trunc(decimal,n=2){ let x = decimal + ''; // string return x.lastIndexOf('.')>=0?parseFloat(x.substr(0,x.lastIndexOf('.')+(n+1))):decimal; // You can use indexOf() instead of lastIndexOf() } console.log(trunc(-241.31234,2)); console.log(trunc(241.312,5)); console.log(trunc(-241.233)); console.log(trunc(241.2,0)); console.log(trunc(241));
la source
J'ai trouvé un problème: vu la situation suivante: 2.1 ou 1.2 ou -6.4
Que faire si vous voulez toujours 3 décimales ou deux ou n'importe quoi, donc, vous devez compléter les zéros de tête à droite
// 3 decimals numbers 0.5 => 0.500 // 6 decimals 0.1 => 0.10000 // 4 decimales -2.1 => -2.1000 // truncate to 3 decimals 3.11568 => 3.115
C'est la fonction fixe de Nick Knowlson
function truncateDecimals (num, digits) { var numS = num.toString(); var decPos = numS.indexOf('.'); var substrLength = decPos == -1 ? numS.length : 1 + decPos + digits; var trimmedResult = numS.substr(0, substrLength); var finalResult = isNaN(trimmedResult) ? 0 : trimmedResult; // adds leading zeros to the right if (decPos != -1){ var s = trimmedResult+""; decPos = s.indexOf('.'); var decLength = s.length - decPos; while (decLength <= digits){ s = s + "0"; decPos = s.indexOf('.'); decLength = s.length - decPos; substrLength = decPos == -1 ? s.length : 1 + decPos + digits; }; finalResult = s; } return finalResult; };
https://jsfiddle.net/huttn155/7/
la source
x = 0.0000
le testtruncateDecimals (x, 2)
échoue. revient0
. pas comme prévu0.00
function toFixed(number, digits) { var reg_ex = new RegExp("(\\d+\\.\\d{" + digits + "})(\\d)") var array = number.toString().match(reg_ex); return array ? parseFloat(array[1]) : number.valueOf() } var test = 10.123456789 var __fixed = toFixed(test, 6) console.log(__fixed) // => 10.123456
la source
La réponse de @kirilloid semble être la bonne réponse, cependant, le code principal doit être mis à jour. Sa solution ne prend pas en charge les nombres négatifs (que quelqu'un a mentionnés dans la section des commentaires mais n'a pas été mis à jour dans le code principal).
Mettre à jour cela vers une solution finale testée complète:
Number.prototype.toFixedDown = function(digits) { var re = new RegExp("([-]*\\d+\\.\\d{" + digits + "})(\\d)"), m = this.toString().match(re); return m ? parseFloat(m[1]) : this.valueOf(); };
Utilisation de l'échantillon:
var x = 3.1415629; Logger.log(x.toFixedDown(2)); //or use whatever you use to log
Violon: Numéro JS Arrondi vers le bas
PS: pas assez de repo pour commenter cette solution.
la source
Voici une fonction simple mais fonctionnelle pour tronquer le nombre jusqu'à 2 décimales.
function truncateNumber(num) { var num1 = ""; var num2 = ""; var num1 = num.split('.')[0]; num2 = num.split('.')[1]; var decimalNum = num2.substring(0, 2); var strNum = num1 +"."+ decimalNum; var finalNum = parseFloat(strNum); return finalNum; }
la source
Le type résultant reste un nombre ...
/* Return the truncation of n wrt base */ var trunc = function(n, base) { n = (n / base) | 0; return base * n; }; var t = trunc(5.467, 0.01);
la source
Lodash a quelques méthodes utilitaires mathématiques qui peuvent arrondir , plancher et plafonner un nombre à une précision décimale donnée. Cela laisse des zéros à la fin.
Ils adoptent une approche intéressante, en utilisant l'exposant d'un nombre. Apparemment, cela évite les problèmes d'arrondi.
(Remarque:
func
estMath.round
ouceil
oufloor
dans le code ci-dessous)// Shift with exponential notation to avoid floating-point issues. var pair = (toString(number) + 'e').split('e'), value = func(pair[0] + 'e' + (+pair[1] + precision)); pair = (toString(value) + 'e').split('e'); return +(pair[0] + 'e' + (+pair[1] - precision));
Lien vers le code source
la source
Voici mon point de vue sur le sujet:
convert.truncate = function(value, decimals) { decimals = (decimals === undefined ? 0 : decimals); return parseFloat((value-(0.5/Math.pow(10, decimals))).toFixed(decimals),10); };
C'est juste une version légèrement plus élaborée de
(f - 0.005).toFixed(2)
la source
Celui qui est marqué comme la solution est la meilleure solution que j'ai trouvée jusqu'à aujourd'hui, mais a un problème sérieux avec 0 (par exemple, 0.toFixedDown (2) donne -0,01). Je suggère donc d'utiliser ceci:
Number.prototype.toFixedDown = function(digits) { if(this == 0) { return 0; } var n = this - Math.pow(10, -digits)/2; n += n / Math.pow(2, 53); // added 1360765523: 17.56.toFixedDown(2) === "17.56" return n.toFixed(digits); }
la source
Voici ce que j'utilise:
var t = 1; for (var i = 0; i < decimalPrecision; i++) t = t * 10; var f = parseFloat(value); return (Math.floor(f * t)) / t;
la source
const TO_FIXED_MAX = 100; function truncate(number, decimalsPrecison) { // make it a string with precision 1e-100 number = number.toFixed(TO_FIXED_MAX); // chop off uneccessary digits const dotIndex = number.indexOf('.'); number = number.substring(0, dotIndex + decimalsPrecison + 1); // back to a number data type (app specific) return Number.parseFloat(number); } // example truncate(0.00000001999, 8); 0.00000001
marche avec:
la source
juste pour souligner une solution simple qui a fonctionné pour moi
convertissez-le en chaîne puis regexez-le ...
var number = 123.45678; var number_s = '' + number; var number_truncated_s = number_s.match(/\d*\.\d{4}/)[0] var number_truncated = parseFloat(number_truncated_s)
Il peut être abrégé en
var number_truncated = parseFloat(('' + 123.4568908).match(/\d*\.\d{4}/)[0])
la source
Voici un code ES6 qui fait ce que vous voulez
const truncateTo = (unRouned, nrOfDecimals = 2) => { const parts = String(unRouned).split("."); if (parts.length !== 2) { // without any decimal part return unRouned; } const newDecimals = parts[1].slice(0, nrOfDecimals), newString = `${parts[0]}.${newDecimals}`; return Number(newString); }; // your examples console.log(truncateTo(5.467)); // ---> 5.46 console.log(truncateTo(985.943)); // ---> 985.94 // other examples console.log(truncateTo(5)); // ---> 5 console.log(truncateTo(-5)); // ---> -5 console.log(truncateTo(-985.943)); // ---> -985.94
la source
Number.prototype.truncate = function(places) { var shift = Math.pow(10, places); return Math.trunc(this * shift) / shift; };
la source
Vous pouvez travailler avec des chaînes. Il vérifie si "." existe, puis supprime une partie de la chaîne.
tronquer (7,88, 1) -> 7,8
tronquer (7.889, 2) -> 7.89
tronquer (-7,88, 1) -> -7,88
function truncate(number, decimals) { const tmp = number + ''; if (tmp.indexOf('.') > -1) { return +tmp.substr(0 , tmp.indexOf('.') + decimals+1 ); } else { return +number } }
la source
Je ne comprends pas vraiment pourquoi il y a tant de réponses différentes à une question aussi fondamentalement simple; il n'y a que deux approches que j'ai vues qui semblent valoir la peine d'être examinées. J'ai fait un test rapide pour voir la différence de vitesse en utilisant https://jsbench.me/ .
C'est la solution qui est actuellement (26/09/2020) signalée comme la réponse:
function truncate(n, digits) { var re = new RegExp("(\\d+\\.\\d{" + digits + "})(\\d)"), m = n.toString().match(re); return m ? parseFloat(m[1]) : n.valueOf(); }; [ truncate(5.467,2), truncate(985.943,2), truncate(17.56,2), truncate(0, 1), truncate(1.11, 1) + 22];
Cependant, cela fait des trucs de chaînes et d'expressions régulières, ce qui n'est généralement pas très efficace, et il existe une fonction Math.trunc qui fait exactement ce que l'OP veut, sans décimales. Par conséquent, vous pouvez facilement utiliser cela plus un peu d'arithmétique supplémentaire pour obtenir la même chose.
Voici une autre solution que j'ai trouvée sur ce fil, qui est celle que j'utiliserais:
function truncate(n, digits) { var step = Math.pow(10, digits || 0); var temp = Math.trunc(step * n); return temp / step; } [ truncate(5.467,2), truncate(985.943,2), truncate(17.56,2), truncate(0, 1), truncate(1.11, 1) + 22];
La première méthode est "99,92% plus lente" que la seconde, donc la seconde est définitivement celle que je recommanderais d'utiliser.
Bon, revenons à la recherche d'autres moyens d'éviter le travail ...
la source