bit4fox
bit4fox

Reputation: 2121

Get number of digits with JavaScript

As the title of my post suggests, I would like to know how many digits var number has. For example: If number = 15; my function should return 2. Currently, it looks like this:

function getlength(number) {
  return number.toString().length();
}

But Safari says it is not working due to a TypeError:

'2' is not a function (evaluating 'number.toString().length()')

As you can see, '2' is actually the right solution. But why is it not a function?

Upvotes: 191

Views: 371751

Answers (22)

Jorge Santos
Jorge Santos

Reputation: 46

this solution is simple and clean

function countNumberAfterDigit(num) {
  const array = num.toString().split('.');
  // array[0] = numbers before digit
  // array[1] = numbers after digit

 return array[0].length + array[1].length
}

Upvotes: 0

Seth Falco
Seth Falco

Reputation: 630

I've just spent an unhealthy amount of time reviewing this, so I'm sharing my findings.

There is no single optimal solution to this. It depends on what the range of values you need to support. You can merge multiple solutions to balance performance and correctness, though.

The main caveats that make this complicated are:

  • Trying to parse it with pure math doesn't go well, try 0.1 + 0.2 in your console and see the result. It's very challenging to get meaningful results using primitive math operations if you want to support floating-point numbers.
  • JavaScript doesn't display the full length of numbers that have many digits, so even the simple solutions like String.length aren't great.

I'll include benchmarks with all implementations, but note that some handle particular types of input better. You should evaluate them based on the input you expect to receive.

Here is how my benchmark looks. Note that each implementation has two benchmarks noted under it. One for all values, including the ones that aren't supported, and with only 32-bit integers as they're supported by all implementations.

const benchmark = require('benchmark');
const suite = new benchmark.Suite;

const data = [      // Digits
  Number.MIN_VALUE, // 325
  -123143,          // 6
  -0.12,            // 3
  0,                // 1
  0.000123,         // 7
  0.12,             // 3
  1,                // 1
  123.123,          // 6
  234524,           // 6
  1000000,          // 7
  Number.MAX_VALUE  // 309
];

function countDigits(num) {
  // …
}

suite
  .add('Benchmark', () => data.map(d => countDigits(d)))
  .on('cycle', (event) => console.log(String(event.target)))
  .run({ 'async': true });

Correctness

First, looking purely at handling a wide range of values correctly. This is the fastest implementation I could come up with that returns the correct result for as many values as possible.

It merges Caltrop's and Mwr247's answer, and handles cases that were missed by both.

function countDigits(num) {
  if (num === 0) {
    return 1;
  }

  if (Number.isInteger(num)) {
    return Math.floor(Math.log10(Math.abs(num))) + 1;
  }

  num = Math.abs(num);
  const str = "" + num;
  const e = str.indexOf('e', 1);

  if (e === -1) {
    return str.length - 1;
  }

  const s1 = str.slice(0, e);
  const s2 = str.slice(e + 1);

  if (num >= 1) {
    return parseInt(s2) + 1;
  }

  return s1[1] !== '.'
    ? Math.abs(parseInt(s2)) + 1
    : Math.abs(parseInt(s2)) + s1.length - 1;
}

// All x 5,296,360 ops/sec ±0.85% (96 runs sampled)
// 32-bit integers x 15,941,480 ops/sec ±1.19% (97 runs sampled)

Compromising

Chances are you expect specific input and so don't have to worry about the extreme numbers, so a more performant solution can be worthwhile.

Caltrop's answer handles positives, negatives, and floating points. The downsides are that it doesn't work for large numbers. The string representation of integers over 20 digits and large floating points are standard notation (i.e. 5e-324) so they'll get miscounted.

Here is a derived version with one change, which runs faster for me:

function countDigits(num) {
  num = Math.abs(num);
  return Number.isInteger(num) ? ("" + num).length : ("" + num).length - 1;
}

// All x 3,986,610 ops/sec ±1.51% (88 runs sampled)
// 32-bit integers x 49,595,986 ops/sec ±1.55% (92 runs sampled)
//
// Incorrect result for Number.MIN_VALUE and Number.MAX_VALUE
  • Uses Number.isInteger instead of (num << 0) - num.
  • More accurate with input like Number.MAX_VALUE as this returns 23 instead of 22… though both are wrong regardless.

Mwr247 shared two great implementations, but both only work with integers. However, there is a difference between them. The solution that bit shifts will not work with values that are too large either, as bit operations are limited to 32-bit numbers.

function countDigits(x) {
  return Math.max(Math.floor(Math.log10(Math.abs(x))), 0) + 1;
}

// All x 5,704,235 ops/sec ±1.70% (92 runs sampled)
// 32-bit integers x 16,256,824 ops/sec ±1.28% (93 runs sampled)
//
// Incorrect result for Number.MIN_VALUE, -0.12, 0.000123, 0.12, 123.123

function countDigits(x) {
  return (Math.log10((x ^ (x >> 31)) - (x >> 31)) | 0) + 1;
}

// All x 8,428,740 ops/sec ±1.51% (94 runs sampled)
// 32-bit integers x 16,327,264 ops/sec ±3.23% (86 runs sampled)
//
// Incorrect result for Number.MIN_VALUE, -0.12, 0.000123, 0.12, 123.123, Number.MAX_VALUE

Other solution I've found or have tried to come up with either have performed slower, or don't provide any benefit over those listed above.

Notes

  • Regular expressions can't keep up with the proposed solutions provided here, and suffer from the same caveats as other string parsing solutions.
  • Solutions that use Math operations will impact performance before you're able to address precision issues if you want to support floating points.

Upvotes: 0

Reinis
Reinis

Reputation: 136

heres a correct mathematical answer (using logarithms) that is also well explained:

function numberOfDigitsInIntegerPart(numberToGetDigitsFor: number): number {
    const valueWithoutNegative = Math.abs(numberToGetDigitsFor);

    if (valueWithoutNegative === 0) {
        // Math.log10(0) === -Infinity
        return 1;
    }

    if (valueWithoutNegative > 0 && valueWithoutNegative < 1) {
        // Math.log10(0.1) === -1
        // Math.log10(0.2) === -0.6989700043360187
        // etc
        return 1;
    }

    if (valueWithoutNegative === 1) {
        // Math.log10(1) === 0
        return 1;
    }

    // Math.log10(1.1) === 0.04139268515822507
    // Math.log10(2000) === 3.3010299956639813
    // Math.log10(10000) ==== 4
    // etc

    const powerToWhich10MustBeExponentiatedToGetValue = Math.log10(valueWithoutNegative);
    const closestRoundPowerBelowExponentationToGetValue = Math.floor(powerToWhich10MustBeExponentiatedToGetValue);

    return closestRoundPowerBelowExponentationToGetValue + 1;
}

Logarithms, for those, who've forgotten highschool maths classes (I know I had before writing this answer) are the opposites of power. Math.log10(x) is asking "to what power do I need to multiply 10 to get x"?

So

Math.log10(100) will be 2, because 10^2 (10x10) is 100,

Math.log10(1000) will be 3, because 10^3 (10x10x10) is 1000

etc

Upvotes: 0

Mwr247
Mwr247

Reputation: 1390

Here's a mathematical answer (also works for negative numbers):

function numDigits(x) {
  return Math.max(Math.floor(Math.log10(Math.abs(x))), 0) + 1;
}

And an optimized version of the above (more efficient bitwise operations): *

function numDigits(x) {
  return (Math.log10((x ^ (x >> 31)) - (x >> 31)) | 0) + 1;
}

Essentially, we start by getting the absolute value of the input to allow negatives values to work correctly. Then we run through the log10 operation to give us what power of 10 the input is (if you were working in another base, you would use the logarithm for that base), which is the number of digits. Then we floor the output to only grab the integer part of that. Finally, we use the max function to fix decimal values (any fractional value between 0 and 1 just returns 1, instead of a negative number), and add 1 to the final output to get the count.

The above assumes (based on your example input) that you wish to count the number of digits in integers (so 12345 = 5, and thus 12345.678 = 5 as well). If you would like to count the total number of digits in the value (so 12345.678 = 8), then add this before the 'return' in either function above:

x = Number(String(x).replace(/[^0-9]/g, ''));

* Please note that bitwise operations in JavaScript only work with 32-bit values (max of 2,147,483,647). So don't go using the bitwise version if you expect numbers larger than that, or it simply won't work.

Upvotes: 107

DevAddict
DevAddict

Reputation: 2013

you can use the Math.abs function to turn negative numbers to positive and keep positives as it is. then you can convert the number to string and provide length.

Math.abs(num).toString().length;

i found this method the easiest and it works pretty good. but if you are sure you will be provided with positive number you can just turn it to string and then use length.

num.toString().length

Upvotes: 4

Dana Woodman
Dana Woodman

Reputation: 4522

While not technically answering this question, if you're looking for the length of the fractional part of a number (e.g. 1.35 => 2 or 1 => 0), this may help you:

function fractionalDigitLength(num) {
  if (Number.isInteger(num)) return 0;
  return String(num).split('.')[1].length;
}

Note: Reason I'm posting here as I think people googling this answer may also want a solution to just getting the fractional length of a number.

Upvotes: 1

Idan
Idan

Reputation: 4023

You can use in this trick:

(''+number).length

Upvotes: 7

ganesh phirke
ganesh phirke

Reputation: 473

for interger digit we can also implement continuously dividing by 10 :

var getNumberOfDigits = function(num){
    var count = 1;
    while(Math.floor(num/10) >= 1){
        num = Math.floor(num/10);
        ++count;
    }
    return count;
}

console.log(getNumberOfDigits(1))
console.log(getNumberOfDigits(12))
console.log(getNumberOfDigits(123))

Upvotes: 0

Caltrop
Caltrop

Reputation: 935

A solution that also works with both negative numbers and floats, and doesn't call any expensive String manipulation functions:

function getDigits(n) {
   var a = Math.abs(n);            // take care of the sign
   var b = a << 0;                 // truncate the number
   if(b - a !== 0) {               // if the number is a float
       return ("" + a).length - 1; // return the amount of digits & account for the dot
   } else {
       return ("" + a).length;     // return the amount of digits
   }
}

Upvotes: 1

Priya Shalini
Priya Shalini

Reputation: 11

Please use the following expression to get the length of the number.

length = variableName.toString().length

Upvotes: 1

Rajat Srivastava
Rajat Srivastava

Reputation: 125

`You can do it by simple loop using Math.trunc() function. if in interview interviewer ask to do it without converting it into string`
    let num = 555194154234 ;
    let len = 0 ;
    const numLen = (num) => {
     for(let i = 0; i < num ||  num == 1 ; i++){
        num = Math.trunc(num/10);
        len++ ;
     }
      return len + 1 ;
    }
    console.log(numLen(num));

Upvotes: 1

A P
A P

Reputation: 109

it would be simple to get the length as

  `${NUM}`.length

where NUM is the number to get the length for

Upvotes: 10

Juliana Melo
Juliana Melo

Reputation: 19

Here is my solution. It works with positive and negative numbers. Hope this helps

function findDigitAmount(num) {

   var positiveNumber = Math.sign(num) * num;
   var lengthNumber = positiveNumber.toString();

 return lengthNumber.length;
}


(findDigitAmount(-96456431);    // 8
(findDigitAmount(1524):         // 4

Upvotes: 0

Ericgit
Ericgit

Reputation: 7063

Note : This function will ignore the numbers after the decimal mean dot, If you wanna count with decimal then remove the Math.floor(). Direct to the point check this out!

function digitCount ( num )
{
     return Math.floor( num.toString()).length;
}

 digitCount(2343) ;

// ES5+

 const digitCount2 = num => String( Math.floor( Math.abs(num) ) ).length;

 console.log(digitCount2(3343))

Basically What's going on here. toString() and String() same build-in function for converting digit to string, once we converted then we'll find the length of the string by build-in function length.

Alert: But this function wouldn't work properly for negative number, if you're trying to play with negative number then check this answer Or simple put Math.abs() in it;

Cheer You!

Upvotes: 2

Yogesh Aggarwal
Yogesh Aggarwal

Reputation: 1022

Problem statement: Count number/string not using string.length() jsfunction. Solution: we could do this through the Forloop. e.g

for (x=0; y>=1 ; y=y/=10){
  x++;
}

if (x <= 10) {
  this.y = this.number;                
}   

else{
  this.number = this.y;
}    

}

Upvotes: 0

Rafael Mel&#243;n
Rafael Mel&#243;n

Reputation: 1

Two digits: simple function in case you need two or more digits of a number with ECMAScript 6 (ES6):

const zeroDigit = num => num.toString().length === 1 ? `0${num}` : num;

Upvotes: -1

Muhammad Awais
Muhammad Awais

Reputation: 4492

The length property returns the length of a string (number of characters).

The length of an empty string is 0.

var str = "Hello World!";
var n = str.length;

The result of n will be: 12

    var str = "";
    var n = str.length;

The result of n will be: 0


Array length Property:


The length property sets or returns the number of elements in an array.

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.length;

The result will be: 4

Syntax:

Return the length of an array:

array.length

Set the length of an array:

array.length=number

Upvotes: -8

user40521
user40521

Reputation: 2119

var i = 1;
while( ( n /= 10 ) >= 1 ){ i++ }

23432          i = 1
 2343.2        i = 2
  234.32       i = 3
   23.432      i = 4
    2.3432     i = 5
    0.23432

Upvotes: 3

VisioN
VisioN

Reputation: 145398

length is a property, not a method. You can't call it, hence you don't need parenthesis ():

function getlength(number) {
    return number.toString().length;
}

UPDATE: As discussed in the comments, the above example won't work for float numbers. To make it working we can either get rid of a period with String(number).replace('.', '').length, or count the digits with regular expression: String(number).match(/\d/g).length.

In terms of speed potentially the fastest way to get number of digits in the given number is to do it mathematically. For positive integers there is a wonderful algorithm with log10:

var length = Math.log(number) * Math.LOG10E + 1 | 0;  // for positive integers

For all types of integers (including negatives) there is a brilliant optimised solution from @Mwr247, but be careful with using Math.log10, as it is not supported by many legacy browsers. So replacing Math.log10(x) with Math.log(x) * Math.LOG10E will solve the compatibility problem.

Creating fast mathematical solutions for decimal numbers won't be easy due to well known behaviour of floating point math, so cast-to-string approach will be more easy and fool proof. As mentioned by @streetlogics fast casting can be done with simple number to string concatenation, leading the replace solution to be transformed to:

var length = (number + '').replace('.', '').length;  // for floats

Upvotes: 321

Nate
Nate

Reputation: 21

I'm still kind of learning Javascript but I came up with this function in C awhile ago, which uses math and a while loop rather than a string so I re-wrote it for Javascript. Maybe this could be done recursively somehow but I still haven't really grasped the concept :( This is the best I could come up with. I'm not sure how large of numbers it works with, it worked when I put in a hundred digits.

function count_digits(n) {
    numDigits = 0;
    integers = Math.abs(n);

    while (integers > 0) {
        integers = (integers - integers % 10) / 10;
        numDigits++;
    }
    return numDigits;
}

edit: only works with integer values

Upvotes: 2

Maciej Maciej
Maciej Maciej

Reputation: 21

If you need digits (after separator), you can simply split number and count length second part (after point).

function countDigits(number) {
    var sp = (number + '').split('.');
    if (sp[1] !== undefined) {
        return sp[1].length;
    } else {
        return 0;
    }
}

Upvotes: 2

streetlogics
streetlogics

Reputation: 4730

Since this came up on a Google search for "javascript get number of digits", I wanted to throw it out there that there is a shorter alternative to this that relies on internal casting to be done for you:

var int_number = 254;
var int_length = (''+int_number).length;

var dec_number = 2.12;
var dec_length = (''+dec_number).length;

console.log(int_length, dec_length);

Yields

3 4

Upvotes: 23

Related Questions