2

I have simple function that calculates number of decimals, eg. _d(0.01) = 2, _d(0.001) = 3 and so on.

We added some new coins to our system that have 0.00000001 quantity and function broke.

Here is why: 0.00000001.toString() = 1e-8, so I cant split it it by '.' and calculate length of second part as I did before.

So the question is - how to get string '0.00000001' out of 0.00000001 number easiest way.

EDIT I didnt mean exactly '0.00000001', I meant any micronumber to decimal without exp. Some function _d(x) that would work _d(0.000000000012) = '0.000000000012'and so on. What usually toString() does to large (but not too large) numbers.

Denis Matafonov
  • 2,684
  • 23
  • 30

5 Answers5

4

Use toFixed() with a large number of digits, then count the number of zeroes after the decimal point.

function _d(num) {
    var str = num.toFixed(100);
    var fraction = str.split('.')[1];
    var zeros = fraction.match(/^0*/)[0].length;
    return zeros + 1;
}
console.log(_d(0.1));
console.log(_d(0.01));
console.log(_d(0.000000001));
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • 1
    Woudnt work for, cause I have to know how many numbers after comma there are. In toFixed(20) I'll always have 20. – Denis Matafonov Nov 21 '17 at 20:31
  • All you care about is the number of leading zeroes after the decimal, right? You can ignore the rest. – Barmar Nov 21 '17 at 20:33
  • To ignore trailing zeroes I'll have to use another, even more havier function. I think there should be an easier solution. – Denis Matafonov Nov 21 '17 at 20:38
  • Maybe you shouldn't be using floating point in the first place. – Barmar Nov 21 '17 at 20:44
  • @DenisMatafonov See the full code in my updated answer. – Barmar Nov 21 '17 at 20:50
  • genious! Accepted. Simple, lightweight, unversal. Great. – Denis Matafonov Nov 21 '17 at 20:53
  • oops. `console.log(_d(0.00000000123)); //9, but should be 12` – Denis Matafonov Nov 21 '17 at 20:55
  • That's not clear from the question, which doesn't have examples with more than one non-zero digit. – Barmar Nov 21 '17 at 20:57
  • Floating point is really the wrong datatype to use, because it introduces errors. If you print that with too many digits, it will add extra non-zero trailing digits, e.g. `0.000000001230000000000000095218`. There's no way to know which digits are really sigificant. – Barmar Nov 21 '17 at 20:58
  • Yep, my bad. But I cant ignore ...23 at the end – Denis Matafonov Nov 21 '17 at 20:59
  • `0.000000001230000000000000095218` - in this case all digits are significant, but I dont know programmatically how many there are. – Denis Matafonov Nov 21 '17 at 21:00
  • I mean if I have string, its easy `'0.000000001230000000000000095218'.split('.')[1].length = 30`, but what if I have number 0.000000001230000000000000095218 ? How to get how many digits are there, after the dot(comma)? – Denis Matafonov Nov 21 '17 at 21:02
  • But that's the number you get when you enter `0.00000000123` and show 30 digits -- those extra digits at the end are not part of your original input, they're because floating point can't represent many decimal fractions exactly. – Barmar Nov 21 '17 at 21:02
  • There's no way to know which digits were in the original input, and which were due to floating point roundoff error. – Barmar Nov 21 '17 at 21:02
2

Do you want some thing like this

function decimalPlaces(num) {
  var match = (''+num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
  if (!match) { return 0; }
  return Math.max(
       0,
       // Number of digits right of decimal point.
       (match[1] ? match[1].length : 0)
       // Adjust for scientific notation.
       - (match[2] ? +match[2] : 0));
}

console.log(decimalPlaces(0.000000001))
Abid Nawaz
  • 866
  • 6
  • 20
1

First off, I got some inspiration for this answer from here: How to avoid scientific notation for large numbers in JavaScript?

You can convert the number to a strong and then check for str.indexOf("e"). If true, then just return the scientific notation part of the string. For example:

  function _d() {
    // your current function here
    if (str.indexOf("e")) {
      var something = str.split("-")[1];
      return something;
    }
  }

EDIT: I was working on this before your last comment to me, so this returns a string of the number, which I thought was what you wanted. Leaving aside the point about significant digits, which is meaningful and correct but does not solve your problem, try this. We take the number, convert to string, if that string is not scientific notation then the answer is trivial. If it is scientific notation, then split the string twice (once on "e-" and then split the zeroth array on "." Add str[1]-1 zeroes to the lead of the number and add the digits to the end.

function _d(arg) {
  var str = arg.toString();
  if (str.indexOf("e-")) {
    var digits = str.split("e-")[0];
    var zeroes = str.split("e-")[1];
    var zero = Number(zeroes);
    var each = digits.split(".");
    var something = "0.";
    for (var i = 0; i < zeroes-1; i++) {
      something += "0";
    }
    for (var j = 0; j < each.length; j++) {
      something = something + each[j];
    }
    return something;
  }
}

This won't work with very large numbers or very small negative numbers. And its pretty convoluted.

ecg8
  • 1,362
  • 1
  • 12
  • 16
0

To keep it as the full decimal:

Number(0.000001)
// 0.000001

To show it as a string:

0.000001.toFixed(6)
// "0.000001"

enter image description here

Kristian
  • 21,204
  • 19
  • 101
  • 176
0

The other way is to use .toString() and then look for .length-2(2 characters - '0.'. It should give you the number of zeros.

The advantage of this method is you don't need to know the number of maximum decimals in the number.

sofalse
  • 77
  • 1
  • 14