Ce que j'aimerais avoir, c'est presque le contraire de Number.prototype.toPrecision (), ce qui signifie que quand j'ai un nombre, combien de décimales y a-t-il? Par exemple.
(12.3456).getDecimals() // 4
Pour ceux qui se demandent comment faire cela plus rapidement (sans convertir en chaîne), voici une solution:
function precision(a) {
var e = 1;
while (Math.round(a * e) / e !== a) e *= 10;
return Math.log(e) / Math.LN10;
}
Edit: une solution plus complète avec les cas Edge couverts:
function precision(a) {
if (!isFinite(a)) return 0;
var e = 1, p = 0;
while (Math.round(a * e) / e !== a) { e *= 10; p++; }
return p;
}
Une solution possible (dépend de l'application):
var precision = (12.3456 + "").split(".")[1].length;
Si par "précision" vous voulez dire "décimales", c'est impossible, car les flottants sont binaires . Ils n'ont pas ont décimales, et la plupart des valeurs comportant un petit nombre de décimales ont des chiffres récurrents en binaire, et lorsqu'elles sont converties en décimales, elles ne donnent pas nécessairement le nombre décimal d'origine. .
Tout code fonctionnant avec les "décimales" d'un flottant est susceptible de produire des résultats inattendus sur certains nombres.
Basé sur la méthode de @ boolean_Type pour gérer les exposants, mais en évitant les expressions rationnelles:
function getPrecision (value) {
if (!isFinite(value)) { return 0; }
const [int, float = ''] = Number(value).toFixed(12).split('.');
let precision = float.length;
while (float[precision - 1] === '0' && precision >= 0) precision--;
return precision;
}
Essayez ce qui suit
function countDecimalPlaces(number) {
var str = "" + number;
var index = str.indexOf('.');
if (index >= 0) {
return str.length - index - 1;
} else {
return 0;
}
}
Il n'y a pas de fonction native pour déterminer le nombre de décimales. Ce que vous pouvez faire est de convertir le nombre en chaîne, puis de compter le décalage sur le délimiteur décimal .
:
Number.prototype.getPrecision = function() {
var s = this + "",
d = s.indexOf('.') + 1;
return !d ? 0 : s.length - d;
};
(123).getPrecision() === 0;
(123.0).getPrecision() === 0;
(123.12345).getPrecision() === 5;
(1e3).getPrecision() === 0;
(1e-3).getPrecision() === 3;
Mais il est dans la nature des flotteurs de vous tromper. 1
peut aussi bien être représenté par 0.00000000989
ou quelque chose d'autre. Je ne suis pas sûr de la performance réelle de ce qui précède dans les applications réelles.
En vous basant sur le commentaire @ blackpla9ue et en considérant le format exponentiel des nombres:
function getPrecision (num) {
var numAsStr = num.toFixed(10); //number can be presented in exponential format, avoid it
numAsStr = numAsStr.replace(/0+$/g, '');
var precision = String(numAsStr).replace('.', '').length - num.toFixed().length;
return precision;
}
getPrecision(12.3456); //4
getPrecision(120.30003300000); //6, trailing zeros are truncated
getPrecision(15); //0
getPrecision(120.000)) //0
getPrecision(0.0000005); //7
getPrecision(-0.01)) //2
Voici quelques exemples, un qui utilise une bibliothèque ( BigNumber.js ) et un autre qui n’utilise pas de bibliothèque. Supposons que vous souhaitiez vérifier qu'un nombre saisi (inputNumber
) possède un nombre de décimales inférieur ou égal à un nombre maximal de décimales (tokenDecimals
).
Avec BigNumber.js
import BigNumber from 'bignumber.js'; // ES6
// const BigNumber = require('bignumber.js').default; // CommonJS
const tokenDecimals = 18;
const inputNumber = 0.000000000000000001;
// Convert to BigNumber
const inputNumberBn = new BigNumber(inputNumber);
// BigNumber.js API Docs: http://mikemcl.github.io/bignumber.js/#dp
console.log(`Invalid?: ${inputNumberBn.dp() > tokenDecimals}`);
Sans BigNumber.js
function getPrecision(numberAsString) {
var n = numberAsString.toString().split('.');
return n.length > 1
? n[1].length
: 0;
}
const tokenDecimals = 18;
const inputNumber = 0.000000000000000001;
// Conversion of number to string returns scientific conversion
// So obtain the decimal places from the scientific notation value
const inputNumberDecimalPlaces = inputNumber.toString().split('-')[1];
// Use `toFixed` to convert the number to a string without it being
// in scientific notation and with the correct number decimal places
const inputNumberAsString = inputNumber.toFixed(inputNumberDecimalPlaces);
// Check if inputNumber is invalid due to having more decimal places
// than the permitted decimal places of the token
console.log(`Invalid?: ${getPrecision(inputNumberAsString) > tokenDecimals}`);
Les approches suivantes fonctionnent-elles?
var num = 12.3456
console.log(num - Math.floor(num))
ou
console.log(num - parseInt(num))