Как я могу получить десятичные разряды числа с плавающей запятой в Javascript?

То, что я хотел бы иметь, является почти противоположностью Number.prototype.toPrecision(), означая, что, когда у меня есть число, сколько у него десятичных знаков? Например

(12.3456).getDecimals() // 4

Ответ 1

Для тех, кто задается вопросом, как это сделать быстрее (без преобразования в строку), вот решение:

function precision(a) {
  var e = 1;
  while (Math.round(a * e) / e !== a) e *= 10;
  return Math.log(e) / Math.LN10;
}

Изменить: более полное решение с закрытыми кромками:

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

Ответ 2

Одно из возможных решений (зависит от приложения):

var precision = (12.3456 + "").split(".")[1].length;

Ответ 3

Если под "точностью" вы подразумеваете "десятичные разряды", то это невозможно, потому что float являются двоичными. У них нет десятичных знаков, и большинство значений, которые имеют небольшое число десятичных знаков, имеют повторяющиеся цифры в двоичном формате и когда они переведены обратно в десятичные числа, что не обязательно дает исходное десятичное число.

Любой код, который работает с "десятичными знаками" поплавка, может привести к неожиданным результатам на некоторых номерах.

Ответ 4

Попробуйте выполнить

function countDecimalPlaces(number) { 
  var str = "" + number;
  var index = str.indexOf('.');
  if (index >= 0) {
    return str.length - index - 1;
  } else {
    return 0;
  }
}

Ответ 5

Нет никакой нативной функции для определения количества десятичных знаков. То, что вы можете сделать, это преобразовать число в строку и затем подсчитать смещение от десятичного разделителя .:

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;

Но это в природе поплавков, чтобы обмануть вас. 1 может быть также представлен 0.00000000989 или что-то еще. Я не уверен, насколько хорошо это действительно работает в реальных приложениях.

Ответ 6

Основываясь на комментарии @blackpla9ue и рассматривая экспоненциальный формат чисел:

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

Ответ 7

Основан на методе @boolean_Type для обработки показателей, но избегает регулярного выражения:

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

Ответ 8

Используются ли следующие подходы?

var num = 12.3456
console.log(num - Math.floor(num))

или

console.log(num - parseInt(num))

Ответ 9

Вот пара примеров, один из которых использует библиотеку (BigNumber.js), а другой - без библиотеки. Предположим, вы хотите проверить, что заданное входное число (inputNumber) имеет количество десятичных знаков, которое меньше или равно максимальному количеству десятичных знаков (tokenDecimals).

С 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}');

Без 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}');

Ответ 10

Предполагая, что номер действителен.

let number = 0.999; 
let noOfPlaces = number.includes(".")
                        ? number.toString().split(".").pop().length
                        : 0;