141 votes

Traitement de la précision des flottants en Javascript

J'ai une grande quantité de valeurs numériques y en javascript. Je veux les grouper en les arrondissant au multiple inférieur de x et convertir le résultat en une chaîne de caractères.

Comment contourner l'ennuyeuse précision en virgule flottante ?

Par exemple :

0.2 + 0.4 = 0.6000000000000001

Deux choses que j'ai essayées :

>>> y = 1.23456789 
>>> x = 0.2 
>>> parseInt(Math.round(Math.floor(y/x))) * x; 
1.2000000000000002

et :

>>> y = 1.23456789 
>>> x = 0.2 
>>> y - (y % x)
1.2000000000000002

187voto

Rusty Fausak Points 4306

De ce poste : Comment gérer la précision des nombres à virgule flottante en JavaScript ?

Vous avez quelques options :

  • Utilisez un type de données spécial pour les décimales, par exemple decimal.js
  • Formatez votre résultat avec un nombre fixe de chiffres significatifs, comme ceci : (Math.floor(y/x) * x).toFixed(2)
  • Convertissez tous vos chiffres en nombres entiers

8voto

philipvr Points 1155

Vous pourriez faire quelque chose comme ceci :

> +(Math.floor(y/x)*x).toFixed(15);
1.2

Edit : Il serait préférable d'utiliser big.js.

big.js

Une petite bibliothèque rapide et facile à utiliser pour l'arithmétique décimale de précision arbitraire.

bigX = new Big(x) bigY = new Big(y) bigY.div(bigX).round().times(bigX).toNumber() // => 1.2

4voto

DeveloperH Points 26
> var x = 0.1
> var y = 0.2
> var cf = 10
> x * y
0.020000000000000004
> (x * cf) * (y * cf) / (cf * cf)
0.02

Solution rapide :

var _cf = (function() {
  function _shift(x) {
    var parts = x.toString().split('.');
    return (parts.length < 2) ? 1 : Math.pow(10, parts[1].length);
  }
  return function() { 
    return Array.prototype.reduce.call(arguments, function (prev, next) { return prev === undefined || next === undefined ? undefined : Math.max(prev, _shift (next)); }, -Infinity);
  };
})();

Math.a = function () {
  var f = _cf.apply(null, arguments); if(f === undefined) return undefined;
  function cb(x, y, i, o) { return x + f * y; }
  return Array.prototype.reduce.call(arguments, cb, 0) / f;
};

Math.s = function (l,r) { var f = _cf(l,r); return (l * f - r * f) / f; };

Math.m = function () {
  var f = _cf.apply(null, arguments);
  function cb(x, y, i, o) { return (x*f) * (y*f) / (f * f); }
  return Array.prototype.reduce.call(arguments, cb, 1);
};

Math.d = function (l,r) { var f = _cf(l,r); return (l * f) / (r * f); };

> Math.m(0.1, 0.2)
0.02

Vous pouvez consulter l'explication complète aquí .

2voto

prahaladp Points 11

Regardez ce lien Il m'a beaucoup aidé.

http://www.w3schools.com/jsref/jsref_toprecision.asp

El toPrecision(no_of_digits_required) renvoie un string alors n'oubliez pas d'utiliser le parseFloat() pour convertir en point décimal de la précision requise.

1voto

whaatt Points 21

Pour accomplir cette tâche, je trouverais d'abord le nombre de décimales dans x puis rond y en conséquence. Je l'utiliserais :

y.toFixed(x.toString().split(".")[1].length);

Il devrait convertir x à une chaîne de caractères, la diviser sur la virgule, trouver la longueur de la partie droite, puis y.toFixed(length) devrait être ronde y en fonction de cette longueur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X