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

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

decimalPlaces(5555.0);     //=> 0
decimalPlaces(5555);       //=> 0
decimalPlaces(555.5);      //=> 1
decimalPlaces(555.50);     //=> 1
decimalPlaces(0.0000005);  //=> 7
decimalPlaces(5e-7);       //=> 7
decimalPlaces(0.00000055); //=> 8
decimalPlaces(5.5e-7);     //=> 8

Моим первым инстинктом было использование строковых представлений: разбить на'.', Затем на'e-'и сделайте математику, вот так (пример многословен):

function decimalPlaces(number) {
  var parts = number.toString().split('.', 2),
    integerPart = parts[0],
    decimalPart = parts[1],
    exponentPart;

  if (integerPart.charAt(0) === '-') {
    integerPart = integerPart.substring(1);
  }

  if (decimalPart !== undefined) {
    parts = decimalPart.split('e-', 2);
    decimalPart = parts[0];
  }
  else {
    parts = integerPart.split('e-', 2);
    integerPart = parts[0];
  }
  exponentPart = parts[1];

  if (exponentPart !== undefined) {
    return integerPart.length +
      (decimalPart !== undefined ? decimalPart.length : 0) - 1 +
      parseInt(exponentPart);
  }
  else {
    return decimalPart !== undefined ? decimalPart.length : 0;
  }
}

Для моих примеров выше, эта функция работает. Тем не менее, я не удовлетворен, пока я не проверил все возможные значения, поэтому я отключилсяNumber.MIN_VALUE.

Number.MIN_VALUE;                      //=> 5e-324
decimalPlaces(Number.MIN_VALUE);       //=> 324

Number.MIN_VALUE * 100;                //=> 4.94e-322
decimalPlaces(Number.MIN_VALUE * 100); //=> 324

Сначала это выглядело разумно, но потом я понял, что5e-324 * 10 должно быть5e-323! И тут меня осенило: я имею дело с эффектами квантования очень маленьких чисел. Мало того, что числа квантуется перед хранением; кроме того, некоторые числа, хранящиеся в двоичном формате, имеют неоправданно длинные десятичные представления, поэтому их десятичные представления усекаются. Это прискорбно для меня, потому что это означает, что я не могу получить их истинную десятичную точность, используя их строковые представления.

Итак, я прихожу к вам, сообщество StackOverflow. Кто-нибудь из вас знает надежный способ получить истинную точность числа после запятой?

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

Ответы на вопрос(6)

Ваш ответ на вопрос