Est-ce que j'ai râté quelque chose?
var someNumber = 123.456;
someNumber = someNumber.toFixed(2);
alert(typeof(someNumber));
//alerts string
Pourquoi ne.toFixed()
retourne une chaîne?
Je veux arrondir le nombre à 2 chiffres décimaux.
Est-ce que j'ai râté quelque chose?
var someNumber = 123.456;
someNumber = someNumber.toFixed(2);
alert(typeof(someNumber));
//alerts string
Pourquoi ne.toFixed()
retourne une chaîne?
Je veux arrondir le nombre à 2 chiffres décimaux.
Réponses:
Il renvoie une chaîne car 0,1 et ses puissances (qui sont utilisées pour afficher les fractions décimales) ne sont pas représentables (du moins pas avec une précision totale) dans les systèmes binaires à virgule flottante.
Par exemple, 0,1 est vraiment 0.1000000000000000055511151231257827021181583404541015625 et 0.01 est vraiment 0.01000000000000000020816681711721685132943093776702880859375. (Merci à d' BigDecimal
avoir prouvé mon point. :-P)
Par conséquent (en l'absence de virgule flottante décimale ou de type nombre rationnel), la sortie sous forme de chaîne est le seul moyen de l'ajuster exactement à la précision requise pour l'affichage.
toFixed
s'agit d'une fonction de mise en forme, qui a pour seul but de convertir un nombre en chaîne, en le formatant en utilisant le nombre de décimales spécifié. La raison pour laquelle il renvoie une chaîne est parce qu'il est censé renvoyer une chaîne, et s'il était nommé à la toStringFixed
place, OP ne serait pas surpris des résultats. Le seul problème ici est que OP s'attendait à ce que cela fonctionne comme Math.round
, sans consulter la référence JS.
Number.prototype.toFixed
est une fonction conçue pour formater un nombre avant de l'imprimer. C'est de la famille de toString
, toExponential
et toPrecision
.
Pour arrondir un nombre, procédez comme suit:
someNumber = 42.008;
someNumber = Math.round( someNumber * 1e2 ) / 1e2;
someNumber === 42.01;
// if you need 3 digits, replace 1e2 with 1e3 etc.
// or just copypaste this function to your code:
function toFixedNumber(num, digits, base){
var pow = Math.pow(base||10, digits);
return Math.round(num*pow) / pow;
}
.
Ou si vous voulez une fonction « native », vous pouvez étendre le prototype:
Number.prototype.toFixedNumber = function(digits, base){
var pow = Math.pow(base||10, digits);
return Math.round(this*pow) / pow;
}
someNumber = 42.008;
someNumber = someNumber.toFixedNumber(2);
someNumber === 42.01;
//or even hexadecimal
someNumber = 0xAF309/256 //which is af3.09
someNumber = someNumber.toFixedNumber(1, 16);
someNumber.toString(16) === "af3.1";
Cependant , gardez à l'esprit que polluer le prototype est considéré comme mauvais lorsque vous écrivez un module, car les modules ne devraient pas avoir d'effets secondaires. Donc, pour un module, utilisez la première fonction .
type Number
. Le fait est que +(anyValue)
renvoie toujours un nombre - par exemple. +("45")
revient 45
, +(new Number(42))
revient 42
. C'est un peu comme si vous tapiez fort la fonction. Si vous en prenez l'habitude, vous pouvez éviter beaucoup de bugs :)
someNumber = Math.round( 42.008 * 1e2 ) / 1e2;
n'est pas 42.01
, il est ~42.0099999999999980
. Raison: Le nombre 42.01
n'existe pas et est arrondi au nombre existant le plus proche. btw, éprouvez les numéros par toPrecision(18)
pour l'imprimer avec tous les chiffres pertinents.
J'ai résolu ce problème en modifiant ceci:
someNumber = someNumber.toFixed(2)
...pour ça:
someNumber = +someNumber.toFixed(2);
Cependant, cela convertira le nombre en chaîne et l'analysera à nouveau, ce qui aura un impact significatif sur les performances. Si vous vous souciez des performances ou de la sécurité du type, vérifiez également les autres réponses.
someNumber = Math.round(someNumber * 1e2) / 1e2
! Voir ma réponse pour une manière plus générale.
Pourquoi ne pas l'utiliser parseFloat
?
var someNumber = 123.456;
someNumber = parseFloat(someNumber.toFixed(2));
alert(typeof(someNumber));
//alerts number
Bien sûr, il renvoie une chaîne. Si vous vouliez arrondir la variable numérique, vous utiliseriez plutôt Math.round (). Le but de toFixed est de formater le nombre avec un nombre fixe de décimales à afficher à l'utilisateur .
Qu'attendriez-vous qu'il renvoie lorsqu'il est censé formater un nombre? Si vous avez un nombre, vous ne pouvez pas faire quoi que ce soit avec lui parce que, par exemple 2 == 2.0 == 2.00
, il doit s'agir d'une chaîne.
Pour fournir un exemple de pourquoi il doit s'agir d'une chaîne:
Si vous formatez 1. toFixed (2), vous obtiendrez «1,00».
Ce n'est pas la même chose que 1, car 1 n'a pas 2 décimales.
Je sais que JavaScript n'est pas exactement un langage de performance , mais il y a de fortes chances que vous obteniez de meilleures performances pour un arrondi si vous utilisez quelque chose comme: roundValue = Math.round (value * 100) * 0.01
Parce que son utilisation principale est d'afficher des nombres? Si vous souhaitez arrondir les nombres, utilisez Math.round()
avec des facteurs appropriés.
'42'
c'est un nombre ... ce qui n'est pas le cas. Le fait qu'une chaîne ne contienne que des chiffres n'en fait pas un nombre. Ce n'est pas PHP. :-P
Voici une version légèrement plus fonctionnelle de la réponse m93a
fournie.
const toFixedNumber = (toFixTo = 2, base = 10) => num => {
const pow = Math.pow(base, toFixTo)
return +(Math.round(num * pow) / pow)
}
const oneNumber = 10.12323223
const result1 = toFixedNumber(2)(oneNumber) // 10.12
const result2 = toFixedNumber(3)(oneNumber) // 10.123
// or using pipeline-operator
const result3 = oneNumber |> toFixedNumber(2) // 10.12