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.

61
demandé sur Rudi Visser 2011-02-06 13:42:08

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);
}
38
répondu kirilloid 2014-05-11 20:46:29

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

49
répondu Nick Knowlson 2017-05-23 10:31:39
var a = 5.467;
var truncated = Math.floor(a * 100) / 100; // = 5.46
25
répondu Dogbert 2011-02-06 10:44:54

vous pouvez corriger l'arrondissement en soustrayant 0.5 pour toFixed, par exemple

(f - 0.005).toFixed(2)
20
répondu RichardTheKiwi 2011-02-06 10:47:14

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

JSFiddle lien .

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.

14
répondu ruffin 2017-05-23 12:18:26

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;
};
9
répondu Daniel X Moore 2014-03-18 00:15:04

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
8
répondu MeestorHok 2016-03-13 01:34:06

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
5
répondu zurfyx 2017-01-14 17:33:08

tronquer en utilisant des opérateurs bitwise:

~~0.5 === 0
~~(-0.5) === 0
~~14.32794823 === 14
~~(-439.93) === -439
4
répondu John Strickler 2016-11-28 14:31:39

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);
}
1
répondu Sebastián Rojas 2014-04-23 21:28:22

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;
            }
1
répondu RohannG 2014-07-22 09:52:43
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
1
répondu Max Zlotskiy 2014-11-23 19:23:47

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;
};

https://jsfiddle.net/huttn155/7/

1
répondu juanpscotto 2015-03-26 21:21:34

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);
1
répondu Bob Lyon 2015-04-25 22:13:00

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));
1
répondu Julio Cesar Cervantes Martinez 2018-04-16 16:58:19

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)
0
répondu opensas 2013-05-15 06:04:28

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])
0
répondu Sergio Campamá 2013-06-07 23:11:56

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;
0
répondu Steve 2014-07-17 11:47:59

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
0
répondu Cristian Sima 2016-08-30 17:19:54
Number.prototype.truncate = function(places) {
  var shift = Math.pow(10, places);

  return Math.trunc(this * shift) / shift;
};
0
répondu Dercni 2017-01-03 05:55:07

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.

0
répondu Jaiwardhan Terminal Swarnakar 2017-10-03 12:29:57
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
0
répondu Flavio 2018-03-14 00:09:56

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));

lien vers le code source

0
répondu Matthias Dailey 2018-07-26 04:47:26