如何在Javascript中获得浮点数的十进制精度?

时间:2022-01-02 16:30:34

Basically, what i would like to have is the opposite of Number.prototype.toPrecision(), meaning that when i have number, what decimal precision does it currently have? E.g.

基本上,我想要的是与number .prototype. toprecision()相反的东西,意思是当我有数字时,它现在有什么十进制精度?如。

(12.3456).getPrecision() // 4

8 个解决方案

#1


15  

One possible solution (depends on the application):

一种可能的解决方案(取决于应用):

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

#2


20  

For anyone wondering how to do this faster (without converting to string), here's a solution:

对于任何想知道如何更快地做到这一点的人(不需要转换为字符串),这里有一个解决方案:

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

Edit: a more complete solution with edge cases covered:

编辑:一个更完整的解决方案,包括边缘案例:

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

#3


3  

If by "precision" you mean "decimal places", then that's impossible because floats are binary. They don't have decimal places, and most values that have a small number of decimal places have recurring digits in binary, and when they're translated back to decimal that doesn't necessarily yield the original decimal number.

如果“precision”指的是“decimal places”,那么这是不可能的,因为float是二进制的。它们没有十进制位,并且大多数有少量十进制位的值都有二进制的循环数字,当它们被转换回十进制时,不一定会产生原始的十进制数。

Any code that works with the "decimal places" of a float is liable to produce unexpected results on some numbers.

任何使用浮点数的“十进制位”的代码都可能对某些数字产生意想不到的结果。

#4


1  

Try the following

试试以下

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

#5


1  

There is no native function to determine the number of decimals. What you can do is convert the number to string and then count the offset off the decimal delimiter .:

没有确定小数个数的本机函数。您可以做的是将数字转换为字符串,然后从十进制分隔符中计数偏移量。

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;

But it's in the nature of floats to fool you. 1 may just as well be represented by 0.00000000989 or something. I'm not sure how well the above actually performs in real life applications.

但是花车的本质就是要愚弄你。1也可以用0。00000000989来表示。我不确定上述方法在实际应用程序中的实际性能如何。

#6


0  

Basing on @blackpla9ue comment and considering numbers exponential format:

基于@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


0  

Does the following approaches work?

以下方法是否有效?

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

or

console.log(num - parseInt(num))

#8


0  

Based on @boolean_Type's method of handling exponents, but avoiding the regex:

基于@boolean_Type处理指数的方法,但避免regex:

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

#1


15  

One possible solution (depends on the application):

一种可能的解决方案(取决于应用):

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

#2


20  

For anyone wondering how to do this faster (without converting to string), here's a solution:

对于任何想知道如何更快地做到这一点的人(不需要转换为字符串),这里有一个解决方案:

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

Edit: a more complete solution with edge cases covered:

编辑:一个更完整的解决方案,包括边缘案例:

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

#3


3  

If by "precision" you mean "decimal places", then that's impossible because floats are binary. They don't have decimal places, and most values that have a small number of decimal places have recurring digits in binary, and when they're translated back to decimal that doesn't necessarily yield the original decimal number.

如果“precision”指的是“decimal places”,那么这是不可能的,因为float是二进制的。它们没有十进制位,并且大多数有少量十进制位的值都有二进制的循环数字,当它们被转换回十进制时,不一定会产生原始的十进制数。

Any code that works with the "decimal places" of a float is liable to produce unexpected results on some numbers.

任何使用浮点数的“十进制位”的代码都可能对某些数字产生意想不到的结果。

#4


1  

Try the following

试试以下

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

#5


1  

There is no native function to determine the number of decimals. What you can do is convert the number to string and then count the offset off the decimal delimiter .:

没有确定小数个数的本机函数。您可以做的是将数字转换为字符串,然后从十进制分隔符中计数偏移量。

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;

But it's in the nature of floats to fool you. 1 may just as well be represented by 0.00000000989 or something. I'm not sure how well the above actually performs in real life applications.

但是花车的本质就是要愚弄你。1也可以用0。00000000989来表示。我不确定上述方法在实际应用程序中的实际性能如何。

#6


0  

Basing on @blackpla9ue comment and considering numbers exponential format:

基于@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


0  

Does the following approaches work?

以下方法是否有效?

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

or

console.log(num - parseInt(num))

#8


0  

Based on @boolean_Type's method of handling exponents, but avoiding the regex:

基于@boolean_Type处理指数的方法,但避免regex:

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