J'essaie de tronquer les nombres décimaux en décimales. Quelque chose comme ça:
5.467 -> 5.46
985.943 -> 985.94
toFixed(2)
fait la bonne chose, mais complète la valeur. Je n'ai pas besoin que la valeur soit arrondie. J'espère que cela est possible en javascript.
upd :
Donc, après tout, les punaises vous hantent toujours, peu importe les efforts que vous déployez pour les compenser. Par conséquent, le problème devrait être résolu 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 solutions ':
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 réponse de Dogbert est bonne, mais si votre code doit traiter des nombres négatifs, Math.floor
seul peut donner des résultats inattendus.
Par exemple. Math.floor(4.3) = 4
, mais Math.floor(-4.3) = -5
Utilisez plutôt une fonction d'assistance 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 incorrectement 17.55
. Pour en savoir plus sur ce phénomène, lisez Ce que tout informaticien devrait savoir sur l’arithmétique en virgule flottante . Malheureusement, l'écriture d'une solution qui élimine toutes les sources d'erreur en virgule flottante est assez délicate avec JavaScript. Dans une autre langue, vous utiliseriez des entiers ou peut-être un type décimal, mais avec javascript ...
Cette solution devrait ê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 aussi éviter les erreurs en virgule flottante, essayez quelque chose comme BigDecimal.js . Vous pouvez trouver d'autres bibliothèques BigDecimal javascript dans cette question SO: "Existe-t-il une bonne bibliothèque Javascript BigDecimal?" et voici un bon article sur des bibliothèques de mathématiques pour Javascript
var a = 5.467;
var truncated = Math.floor(a * 100) / 100; // = 5.46
Vous pouvez corriger l'arrondi en soustrayant 0,5 pour toFixed, par exemple.
(f - 0.005).toFixed(2)
Considérons profitant du double tilde: ~~
) .
Prenez dans le nombre. Multipliez par les chiffres significatifs après la virgule pour que vous puissiez tronquer à zéro avec ~~
. Divisez ce multiplicateur en arrière. Profit.
function truncator(numToTruncate, intDecimalPlaces) {
var numPower = Math.pow(10, intDecimalPlaces); // "numPowerConverter" might be better
return ~~(numToTruncate * numPower)/numPower;
}
J'essaie de résister à l'enveloppe de l'appel ~~
entre parenthèses; L’ordre des opérations devrait permettre que cela fonctionne correctement.
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 également traité des cas pour arrondir à gauche de la virgule.
alert(truncator(4343.123, -2)); // gives 4300.
La logique est un peu farfelue à la recherche de cet usage et pourrait bénéficier d'un remaniement rapide. Mais ça fonctionne toujours. Mieux vaut la chance que le bien.
Je pensais que je donnerais 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;
};
Belle solution à une ligne:
function truncate (num, places) {
return Math.trunc(num * Math.pow(10, places)) / Math.pow(10, places);
}
Puis 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 arrondir et tronquer. Truncating est clairement le comportement que cette question cherche. Si j'appelle tronquer (-3,14) et recevoir -4 en retour, je l'appellerais certainement 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 à l'aide d'opérateurs au niveau des bits:
~~0.5 === 0
~~(-0.5) === 0
~~14.32794823 === 14
~~(-439.93) === -439
J'ai trouvé un problème: vu la situation suivante: 2.1 ou 1.2 ou -6.4
Et si vous voulez toujours 3 décimales ou deux ou wharever, alors, vous devez compléter les zéros à 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;
};
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));
La réponse de @kirilloid semble être la bonne, cependant, le code principal doit être mis à jour. Sa solution ne prend pas en charge les nombres négatifs (ce que quelqu'un a mentionné dans la section commentaire mais n'a pas été mis à jour dans le code principal).
Mise à jour de cette solution complète et testée:
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: Numéro JS Arrondi vers le bas
PS: Pas assez de pension 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é Math qui peuvent arrondir , étage et ceil un nombre avec une précision décimale donnée. Cela laisse les zéros à la fin.
Ils adoptent une approche intéressante en utilisant l’exposant d’un nombre. Cela évite apparemment les problèmes d'arrondi.
(Remarque: 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));
Voici une fonction simple mais pratique pour tronquer les nombres 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;
}
Le type résultant reste un numéro ...
/* 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);
Celui qui marque comme solution est la meilleure solution que j’ai trouvée jusqu’à aujourd’hui, mais qui pose 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);
}
J'ai écrit une réponse en utilisant une méthode plus courte. Voici ce que je suis venu avec
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 si
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, ici vous allez
function truncate(v, p) {
var s = Math.pow(10, p || 0);
return Math.trunc(s * v) / s;
}
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
Number.prototype.truncate = function(places) {
var shift = Math.pow(10, places);
return Math.trunc(this * shift) / shift;
};
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)
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;
juste pour signaler une solution simple qui a fonctionné pour moi
convertissez-le en chaîne puis regex-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])
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