Самый простой способ получить количество десятичных знаков в числе в JavaScript

Есть ли лучший способ выяснить количество десятичных знаков в числе, чем в моем примере?

var nbr = 37.435.45;
var decimals = (nbr!=Math.floor(nbr))?(nbr.toString()).split('.')[1].length:0;

Под «лучше» я подразумеваю более быстрое выполнение и/или использование встроенной функции JavaScript, т.е. что-то вроде nbr.getDecimals().

Заранее спасибо!

РЕДАКТИРОВАТЬ:

После изменения ответа серии 0ne самый быстрый способ, которым я мог бы управлять, это:

var val = 37.435345;
var countDecimals = function(value) {
    if (Math.floor(value) !== value)
        return value.toString().split(".")[1].length || 0;
    return 0;
}
countDecimals(val);

Тест скорости: http://jsperf.com/checkdecimals


person PhilTrep    schedule 28.06.2013    source источник
comment
Взгляните на этот очень подробный ответ stackoverflow.com/questions/10454518/   -  person Reinstate Monica Cellio    schedule 28.06.2013
comment
Спасибо, но спрашивающий указал, что в числах должен быть десятичный знак, а я нет. +1 за интересную ссылку   -  person PhilTrep    schedule 28.06.2013
comment
@PhilippeTrépanier, подумайте, что важнее в общем плане вещей. Как быстро выполняется JavaScript (разница между моим ответом и ответом Пита Д. минимальна) и скорость его загрузки клиенту? Поскольку ответ Пита Д. короче на несколько байтов, лично я оказался бы в затруднительном положении, какой из них выбрать.   -  person Matthew Layton    schedule 28.06.2013
comment
@ series0ne, я в затруднительном положении, но поскольку вы объяснили, как работает ваш код, вы дали прототипный способ сделать это, и ваш ответ был быстрее, чем его, я дал вам правильный ответ.   -  person PhilTrep    schedule 28.06.2013
comment
@PhilippeTrépanier, достаточно честно, я не могу с этим поспорить! :-) Благодарность.   -  person Matthew Layton    schedule 28.06.2013


Ответы (3)


Number.prototype.countDecimals = function () {
    if(Math.floor(this.valueOf()) === this.valueOf()) return 0;
    return this.toString().split(".")[1].length || 0; 
}

При привязке к прототипу это позволяет получить десятичный счет (countDecimals();) непосредственно из числовой переменной.

E.G.

var x = 23.453453453;
x.countDecimals(); // 9

Он работает путем преобразования числа в строку, разбиения на . и возврата последней части массива или 0, если последняя часть массива не определена (что произойдет, если не было десятичного числа). точка).

Если вы не хотите привязывать это к прототипу, вы можете просто использовать это:

var countDecimals = function (value) {
    if(Math.floor(value) === value) return 0;
    return value.toString().split(".")[1].length || 0; 
}

РЕДАКТИРОВАТЬ черным:

Я исправил метод, чтобы он также работал с меньшими числами, такими как 0.000000001

Number.prototype.countDecimals = function () {

    if (Math.floor(this.valueOf()) === this.valueOf()) return 0;

    var str = this.toString();
    if (str.indexOf(".") !== -1 && str.indexOf("-") !== -1) {
        return str.split("-")[1] || 0;
    } else if (str.indexOf(".") !== -1) {
        return str.split(".")[1].length || 0;
    }
    return str.split("-")[1] || 0;
}


var x = 23.453453453;
console.log(x.countDecimals()); // 9

var x = 0.0000000001;
console.log(x.countDecimals()); // 10

var x = 0.000000000000270;
console.log(x.countDecimals()); // 13

var x = 101;  // Integer number
console.log(x.countDecimals()); // 0

person Matthew Layton    schedule 28.06.2013
comment
Спасибо, это именно то, что мне нужно! Я соглашусь, как только закончится время восстановления... - person PhilTrep; 28.06.2013
comment
Нет проблем, добро пожаловать! :-) - person Matthew Layton; 28.06.2013
comment
Это приведет к ошибке для целого числа: jsfiddle.net/3bQqV Но, возможно, это не проблема для OP - person A. Wolff; 28.06.2013
comment
@roasted, хорошо замечено, я поработаю над этим - person Matthew Layton; 28.06.2013
comment
использование по модулю, поскольку ответ Пита Д. был бы быстрее, в любом случае +1 - person A. Wolff; 28.06.2013
comment
после моего последнего комментария, нет, быстрее использовать метод floor() - person A. Wolff; 28.06.2013
comment
@Math.floor, вероятно, быстрее, потому что это функция [собственный код], что означает, что она уже скомпилирована в среду выполнения JS, тогда как эквивалент по модулю должен быть интерпретирован/обработан JIT. - person Matthew Layton; 28.06.2013
comment
Что, если мне нужно знать десятичные дроби числа, введенного внутри ввода? Я пытаюсь сделать это: console.log($('#myinput').val().countDecimals());, но результат: Uncaught TypeError: undefined is not a function - person Andres SK; 19.10.2014
comment
для числа 23.00 он показывает счет как 0 - person Amaldev ps; 31.10.2018
comment
Также выдает ошибку с очень маленькими десятичными суммами. (например, 0,000000001) jsfiddle.net/yh2Lurf5 - person P Roitto; 22.01.2019
comment
В некоторых странах в качестве десятичного разделителя используется запятая, а не точка. В прошлом я использовал этот быстрый и грязный трюк обнаружения, чтобы справиться с этим: var isComma = Boolean(parseFloat(1 / 2).toString().indexOf(",") !== -1); ваша последняя строка будет выглядеть так: return value.toString().split((isComma ? "," : "."))[1].length || 0; - person Balage; 22.03.2019
comment
это не будет работать, когда десятичное значение равно нулю. скажем, 10.0, он возвращает 0, так как мы делаем Math.floor (значение) равно значению. вернуть только this.toString().split(.)[1].length || 0; достаточно для решения - person jaibalaji; 05.02.2020
comment
Я скорее использую его как функцию, потом вы привыкаете к этому в Number, и когда вы переходите на другой проект, у вас его нет. Композиция более гибкая. - person Gubatron; 09.05.2020
comment
Теперь, когда доступна дополнительная цепочка, это может сделать функцию более безопасной (например, NaN) value.toString().split(".")[1]?.length || 0; developer.mozilla.org/de/docs/Web/JavaScript/Reference/ - person Andreas Riedmüller; 18.06.2020
comment
@AndreasRiedmüller null, undefined и NaN будет оцениваться как 0 из-за || 0, но все равно хороший момент. - person Matthew Layton; 18.06.2020
comment
Это не работает для некоторых чисел, например, 0,0000001. - person user3437245; 27.02.2021
comment
Также это приведет к ошибке для экспоненциальных чисел, таких как 8e-7 - person wmbtrmb; 17.05.2021
comment
@Balage Number.prototype.toString() никогда не вернет строку, содержащую запятую, независимо от языка пользователя. - person Adam Leggett; 13.07.2021

Добавление к ответу серии0ne, если вы хотите, чтобы код не выдавал ошибку для целого числа и получал результат 0, когда нет десятичных знаков, используйте это:

var countDecimals = function (value) { 
    if ((value % 1) != 0) 
        return value.toString().split(".")[1].length;  
    return 0;
};
person Pete D    schedule 28.06.2013
comment
может быстрее нравится :var countDecimals = function (value) { return value % 1?value.toString().split(".")[1].length:0; }; - person A. Wolff; 28.06.2013
comment
@OP, вы должны проверить ответы в jsperf, чтобы увидеть, какой из них кажется лучшим. - person A. Wolff; 28.06.2013
comment
Поскольку JavaScript является языком, критически важным для размера, вы можете опустить оператор else. т.е. если (истина) вернуть x; вернуть 0; ... в основном, если он не возвращает количество десятичных знаков, просто верните 0; - person Matthew Layton; 28.06.2013
comment
да, было бы быстрее использовать тернарный, но я думаю, что его легче читать и понимать концепцию. OP может изменить эту концепцию на более быстрый способ. - person Pete D; 28.06.2013
comment
@roasted сделал это, series0ne самый быстрый jsperf.com/checkdecimals - person PhilTrep; 28.06.2013
comment
@PhilippeTrépanier спасибо, интересный результат! - person A. Wolff; 28.06.2013
comment
На самом деле теперь, когда series0ne отредактировал мой код, удалив оператор else, он быстрее, чем его оригинал. Хорошая работа series0ne +1 РЕДАКТИРОВАТЬ: удален ложный jsperf. Виноват. - person Pete D; 28.06.2013
comment
@PeteD ваш jsperf был неправильным, вот правильный: jsperf.com/checkdecimals/4 - person A. Wolff; 28.06.2013

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

Такие вещи, как «Число % 1», возвращают округленное десятичное значение (2,3 % 1 = 0,29999999999999998), и в целом я бы посоветовал вам использовать строки как можно раньше, поскольку приближения с реальными числами могут изменить количество десятичных знаков.

Так что у вас все в порядке, но я поищу способ его оптимизировать.

Редактировать:

function CountDecimalDigits(number)
{
  var char_array = number.toString().split(""); // split every single char
  var not_decimal = char_array.lastIndexOf(".");
  return (not_decimal<0)?0:char_array.length - not_decimal;
}
person Ricola3D    schedule 28.06.2013
comment
У вас отставание на одну ошибку. char_array.length - not_decimal должно быть char_array.length - not_decimal - 1 - person aloisdg; 08.03.2020