Tronquer (pas arrondir) les nombres décimaux en javascript
j'essaie de tronquer les nombres décimaux en décimales. Quelque chose comme ceci:
5.467 -> 5.46
985.943 -> 985.94
toFixed(2)
n'a juste la bonne chose, mais il arrondit la valeur. Je n'ai pas besoin que la valeur soit arrondie. Espérons que cela est possible en javascript.
23 réponses
upd :
donc, après tout ce qui s'est passé, les insectes qui s'approchent vous hanteront toujours, peu importe à quel point vous essayez de les compenser. Par conséquent, le problème devrait être attaqué en représentant des 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]
Vieux erreurs solution 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);
}
Dogbert la réponse est bonne, mais si votre code peut avoir à traiter avec des nombres négatifs, Math.floor
par lui-même peut donner des résultats inattendus.
E. G. Math.floor(4.3) = 4
, mais Math.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 désiré, insérer 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 incorrectement 17.55
. Pour en savoir plus, 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 un autre langage que vous utiliseriez des entiers ou peut-être un type décimal, mais avec javascript...
Cette solution doit être précis à 100%, mais il 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 aussi éviter les erreurs à virgule flottante, essayez quelque chose comme BigDecimal.js . Vous pouvez trouver d'autres bibliothèques javascript BigDecimal dans cette question SO: "y a-t-il un bon Javascript BigDecimal bibliothèque?" et voici un bon billet de blog sur bibliothèques de mathématiques pour Javascript
var a = 5.467;
var truncated = Math.floor(a * 100) / 100; // = 5.46
vous pouvez corriger l'arrondissement en soustrayant 0.5 pour toFixed, par exemple
(f - 0.005).toFixed(2)
prendre en considération profitant de la double tilde: ~~
.
prenez le numéro. Multiplier par les chiffres significatifs après la décimale de sorte que vous pouvez tronquer à zéro place avec ~~
. Divisez-le multiplicateur de retour. Bénéfice.
function truncator(numToTruncate, intDecimalPlaces) {
var numPower = Math.pow(10, intDecimalPlaces); // "numPowerConverter" might be better
return ~~(numToTruncate * numPower)/numPower;
}
j'essaie de résister à l'appel ~~
de parens; l'ordre des opérations devrait faire que cela fonctionne correctement, je croire.
alert(truncator(5.1231231, 1)); // is 5.1
alert(truncator(-5.73, 1)); // is -5.7
alert(truncator(-5.73, 0)); // is -5
EDIT: en regardant en arrière, j'ai involontairement aussi traité des cas pour arrondir à gauche de la décimale aussi bien.
alert(truncator(4343.123, -2)); // gives 4300.
la logique est un peu farfelue à la recherche de cet usage, et peut avantage de un rapide refactoriser. Mais il fonctionne encore. Mieux vaut de la chance que du bien.
j'ai pensé donner une réponse en utilisant |
car c'est simple et fonctionne bien.
truncate = function(number, places) {
var shift = Math.pow(10, places);
return ((number * shift) | 0) / shift;
};
Nice une solution en 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 réponse de @Dogbert peut être améliorée avec Math.trunc
, qui tronque au lieu d'arrondir.
il y a une différence entre l'arrondissement et la troncature. La troncation est de toute évidence, le comportement recherché par cette question. Si je l'appelle troncature(-3,14) et recevoir -4 en arrière, je dirais certainement que indésirable. - @NickKnowlson
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
tronquer en utilisant des opérateurs bitwise:
~~0.5 === 0
~~(-0.5) === 0
~~14.32794823 === 14
~~(-439.93) === -439
celui qui est marque comme la solution est la meilleure solution que j'ai été trouvé jusqu'à aujourd'hui, mais a un grave problème 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);
}
ici est simple mais la fonction de travail pour tronquer le nombre jusqu'à 2 places 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;
}
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
j'ai trouvé un problème: en considérant la situation suivante: 2.1 ou 1.2 ou -6.4
Que faire si vous voulez toujours 3 décimales ou deux ou peu importe, donc, vous devez remplir 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;
};
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);
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));
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 un peu plus élaborée de
(f - 0.005).toFixed(2)
juste pour souligner une solution simple qui a fonctionné pour moi
convertir en string puis regex...
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)
peut être abrégé en
var number_truncated = parseFloat(('' + 123.4568908).match(/\d*\.\d{4}/)[0])
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;
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
Number.prototype.truncate = function(places) {
var shift = Math.pow(10, places);
return Math.trunc(this * shift) / shift;
};
La réponse par @kirilloid semble être la bonne réponse, cependant, le code principal doit être mis à jour. Sa solution ne prend pas en compte les nombres négatifs (ce que quelqu'un a mentionné dans la section commentaires mais n'a pas été mis à jour dans le code principal).
mise à jour vers une solution finale d'essai 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();
};
Exemple D'Utilisation:
var x = 3.1415629;
Logger.log(x.toFixedDown(2)); //or use whatever you use to log
Violon: JS Nombre arrondi à l'inférieur
PS: pas assez de repo pour commenter cette solution.
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
Lodash a quelques méthodes d'utilité de mathématiques qui peuvent rond , plancher , et ceil un nombre à une précision décimale donnée. Cette part 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'arrondissement.
(Note: func
est Math.round
ou ceil
ou floor
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));