Tutorial :How can you get the first digit in an int (C#)?



Question:

In C#, what's the best way to get the 1st digit in an int? The method I came up with is to turn the int into a string, find the 1st char of the string, then turn it back to an int.

int start = Convert.ToInt32(curr.ToString().Substring(0, 1));  

While this does the job, it feels like there is probably a good, simple, math-based solution to such a problem. String manipulation feels clunky.

Edit: irrespective of speed differences, mystring[0] instead of Substring() is still just string manipulation


Solution:1

Here's how

int i = Math.Abs(386792);  while(i >= 10)      i /= 10;  

and i will contain what you need


Solution:2

Benchmarks

Firstly, you must decide on what you mean by "best" solution, of course that takes into account the efficiency of the algorithm, its readability/maintainability, and the likelihood of bugs creeping up in the future. Careful unit tests can generally avoid those problems, however.

I ran each of these examples 10 million times, and the results value is the number of ElapsedTicks that have passed.

Without further ado, from slowest to quickest, the algorithms are:

Converting to a string, take first character

int firstDigit = (int)(Value.ToString()[0]) - 48;  

Results:

12,552,893 ticks  

Using a logarithm

int firstDigit = (int)(Value / Math.Pow(10, (int)Math.Floor(Math.Log10(Value))));  

Results:

9,165,089 ticks  

Looping

while (number >= 10)      number /= 10;  

Results:

6,001,570 ticks  

Conditionals

int firstdigit;  if (Value < 10)       firstdigit = Value;  else if (Value < 100)       firstdigit = Value / 10;  else if (Value < 1000)       firstdigit = Value / 100;  else if (Value < 10000)       firstdigit = Value / 1000;  else if (Value < 100000)       firstdigit = Value / 10000;  else if (Value < 1000000)       firstdigit = Value / 100000;  else if (Value < 10000000)       firstdigit = Value / 1000000;  else if (Value < 100000000)       firstdigit = Value / 10000000;  else if (Value < 1000000000)       firstdigit = Value / 100000000;  else       firstdigit = Value / 1000000000;  

Results:

1,421,659 ticks  

Unrolled & optimized loop

if (i >= 100000000) i /= 100000000;  if (i >= 10000) i /= 10000;  if (i >= 100) i /= 100;  if (i >= 10) i /= 10;  

Results:

1,399,788 ticks  

Note:

each test calls Random.Next() to get the next int


Solution:3

Try this

public int GetFirstDigit(int number) {    if ( number < 10 ) {      return number;    }    return GetFirstDigit ( (number - (number % 10)) / 10);  }  

EDIT

Several people have requested the loop version

public static int GetFirstDigitLoop(int number)  {      while (number >= 10)      {          number = (number - (number % 10)) / 10;      }      return number;  }  


Solution:4

The best I can come up with is:

int numberOfDigits = Convert.ToInt32(Math.Floor( Math.Log10( value ) ) );    int firstDigit = value / Math.Pow( 10, numberOfDigits );  

...

Not very pretty :)

[Edited: first answer was really bad :) ]

[Edit 2: I would probably advise the string manipulating solutions, though]

[Edit 3: code formatting is nice :) ]


Solution:5

variation on Anton's answer:

 // cut down the number of divisions (assuming i is positive & 32 bits)  if (i >= 100000000) i /= 100000000;  if (i >= 10000) i /= 10000;  if (i >= 100) i /= 100;  if (i >= 10) i /= 10;  


Solution:6

Had the same idea as Lennaert

int start = number == 0 ? 0 : number / (int) Math.Pow(10,Math.Floor(Math.Log10(Math.Abs(number))));  

This also works with negative numbers.


Solution:7

If you think Keltex's answer is ugly, try this one, it's REALLY ugly, and even faster. It does unrolled binary search to determine the length.

 ... leading code along the same lines  /* i<10000 */  if (i >= 100){    if (i >= 1000){      return i/1000;    }    else /* i<1000 */{      return i/100;    }  }  else /* i<100*/ {    if (i >= 10){      return i/10;    }    else /* i<10 */{      return i;    }  }  

P.S. MartinStettner had the same idea.


Solution:8

int myNumber = 8383;  char firstDigit = myNumber.ToString()[0];  // char = '8'  


Solution:9

An obvious, but slow, mathematical approach is:

int firstDigit = (int)(i / Math.Pow(10, (int)Math.Log10(i))));  


Solution:10

int temp = i;  while (temp >= 10)  {      temp /= 10;  }  

Result in temp


Solution:11

I know it's not C#, but it's surprising curious that in python the "get the first char of the string representation of the number" is the faster!

EDIT: no, I made a mistake, I forgot to construct again the int, sorry. The unrolled version it's the fastest.

$ cat first_digit.py  def loop(n):      while n >= 10:          n /= 10      return n    def unrolled(n):      while n >= 100000000: # yea... unlimited size int supported :)          n /= 100000000      if n >= 10000:          n /= 10000      if n >= 100:          n /= 100      if n >= 10:          n /= 10      return n    def string(n):      return int(str(n)[0])  $ python -mtimeit -s 'from first_digit import loop as test' \      'for n in xrange(0, 100000000, 1000): test(n)'  10 loops, best of 3: 275 msec per loop  $ python -mtimeit -s 'from first_digit import unrolled as test' \      'for n in xrange(0, 100000000, 1000): test(n)'  10 loops, best of 3: 149 msec per loop  $ python -mtimeit -s 'from first_digit import string as test' \      'for n in xrange(0, 100000000, 1000): test(n)'  10 loops, best of 3: 284 msec per loop  $  


Solution:12

I just stumbled upon this old question and felt inclined to propose another suggestion since none of the other answers so far returns the correct result for all possible input values and it can still be made faster:

public static int GetFirstDigit( int i )  {      if( i < 0 && ( i = -i ) < 0 ) return 2;      return ( i < 100 ) ? ( i < 1 ) ? 0 : ( i < 10 )              ? i : i / 10 : ( i < 1000000 ) ? ( i < 10000 )              ? ( i < 1000 ) ? i / 100 : i / 1000 : ( i < 100000 )              ? i / 10000 : i / 100000 : ( i < 100000000 )              ? ( i < 10000000 ) ? i / 1000000 : i / 10000000              : ( i < 1000000000 ) ? i / 100000000 : i / 1000000000;  }  

This works for all signed integer values inclusive -2147483648 which is the smallest signed integer and doesn't have a positive counterpart. Math.Abs( -2147483648 ) triggers a System.OverflowException and - -2147483648 computes to -2147483648.

The implementation can be seen as a combination of the advantages of the two fastest implementations so far. It uses a binary search and avoids superfluous divisions. A quick benchmark with the index of a loop with 100,000,000 iterations shows that it is twice as fast as the currently fastest implementation.

It finishes after 2,829,581 ticks.

For comparison I also measured a corrected variant of the currently fastest implementation which took 5,664,627 ticks.

public static int GetFirstDigitX( int i )  {      if( i < 0 && ( i = -i ) < 0 ) return 2;      if( i >= 100000000 ) i /= 100000000;      if( i >= 10000 ) i /= 10000;      if( i >= 100 ) i /= 100;      if( i >= 10 ) i /= 10;      return i;  }  

The accepted answer with the same correction needed 16,561,929 ticks for this test on my computer.

public static int GetFirstDigitY( int i )  {      if( i < 0 && ( i = -i ) < 0 ) return 2;      while( i >= 10 )          i /= 10;      return i;  }  

Simple functions like these can easily be proven for correctness since iterating all possible integer values takes not much more than a few seconds on current hardware. This means that it is less important to implement them in a exceptionally readable fashion as there simply won't ever be the need to fix a bug inside them later on.


Solution:13

Very simple (and probably quite fast because it only involves comparisons and one division):

if(i<10)     firstdigit = i;  else if (i<100)     firstdigit = i/10;  else if (i<1000)     firstdigit = i/100;  else if (i<10000)     firstdigit = i/1000;  else if (i<100000)     firstdigit = i/10000;  else (etc... all the way up to 1000000000)  


Solution:14

Did some tests with one of my co-workers here, and found out most of the solutions don't work for numbers under 0.

  public int GetFirstDigit(int number)      {          number = Math.Abs(number); <- makes sure you really get the digit!            if (number < 10)          {              return number;          }          return GetFirstDigit((number - (number % 10)) / 10);      }  


Solution:15

Using all the examples below to get this code:

using System;  using System.Collections.Generic;  using System.Linq;  using System.Text;  using System.Diagnostics;    namespace Benfords  {      class Program      {          static int FirstDigit1(int value)          {              return Convert.ToInt32(value.ToString().Substring(0, 1));          }            static int FirstDigit2(int value)          {              while (value >= 10) value /= 10;              return value;          }              static int FirstDigit3(int value)          {              return (int)(value.ToString()[0]) - 48;          }            static int FirstDigit4(int value)          {              return (int)(value / Math.Pow(10, (int)Math.Floor(Math.Log10(value))));          }            static int FirstDigit5(int value)          {              if (value < 10) return value;              if (value < 100) return value / 10;              if (value < 1000) return value / 100;              if (value < 10000) return value / 1000;              if (value < 100000) return value / 10000;              if (value < 1000000) return value / 100000;              if (value < 10000000) return value / 1000000;              if (value < 100000000) return value / 10000000;              if (value < 1000000000) return value / 100000000;              return value / 1000000000;          }            static int FirstDigit6(int value)          {              if (value >= 100000000) value /= 100000000;              if (value >= 10000) value /= 10000;              if (value >= 100) value /= 100;              if (value >= 10) value /= 10;              return value;          }            const int mcTests = 1000000;            static void Main(string[] args)          {              Stopwatch lswWatch = new Stopwatch();              Random lrRandom = new Random();                int liCounter;                lswWatch.Start();              for (liCounter = 0; liCounter < mcTests; liCounter++)                  FirstDigit1(lrRandom.Next());              lswWatch.Stop();              Console.WriteLine("Test {0} = {1} ticks", 1, lswWatch.ElapsedTicks);                lswWatch.Reset();              lswWatch.Start();              for (liCounter = 0; liCounter < mcTests; liCounter++)                  FirstDigit2(lrRandom.Next());              lswWatch.Stop();              Console.WriteLine("Test {0} = {1} ticks", 2, lswWatch.ElapsedTicks);                lswWatch.Reset();              lswWatch.Start();              for (liCounter = 0; liCounter < mcTests; liCounter++)                  FirstDigit3(lrRandom.Next());              lswWatch.Stop();              Console.WriteLine("Test {0} = {1} ticks", 3, lswWatch.ElapsedTicks);                lswWatch.Reset();              lswWatch.Start();              for (liCounter = 0; liCounter < mcTests; liCounter++)                  FirstDigit4(lrRandom.Next());              lswWatch.Stop();              Console.WriteLine("Test {0} = {1} ticks", 4, lswWatch.ElapsedTicks);                lswWatch.Reset();              lswWatch.Start();              for (liCounter = 0; liCounter < mcTests; liCounter++)                  FirstDigit5(lrRandom.Next());              lswWatch.Stop();              Console.WriteLine("Test {0} = {1} ticks", 5, lswWatch.ElapsedTicks);                lswWatch.Reset();              lswWatch.Start();              for (liCounter = 0; liCounter < mcTests; liCounter++)                  FirstDigit6(lrRandom.Next());              lswWatch.Stop();              Console.WriteLine("Test {0} = {1} ticks", 6, lswWatch.ElapsedTicks);                Console.ReadLine();          }      }  }  

I get these results on an AMD Ahtlon 64 X2 Dual Core 4200+ (2.2 GHz):

Test 1 = 2352048 ticks  Test 2 = 614550 ticks  Test 3 = 1354784 ticks  Test 4 = 844519 ticks  Test 5 = 150021 ticks  Test 6 = 192303 ticks  

But get these on a AMD FX 8350 Eight Core (4.00 GHz)

Test 1 = 3917354 ticks  Test 2 = 811727 ticks  Test 3 = 2187388 ticks  Test 4 = 1790292 ticks  Test 5 = 241150 ticks  Test 6 = 227738 ticks  

So whether or not method 5 or 6 is faster depends on the CPU, I can only surmise this is because the branch prediction in the command processor of the CPU is smarter on the new processor, but I'm not really sure.

I dont have any Intel CPUs, maybe someone could test it for us?


Solution:16

while (i > 10)  {     i = (Int32)Math.Floor((Decimal)i / 10);  }  // i is now the first int  


Solution:17

Non iterative formula:

public static int GetHighestDigit(int num)  {      if (num <= 0)         return 0;         return (int)((double)num / Math.Pow(10f, Math.Floor(Math.Log10(num))));  }  


Solution:18

Just to give you an alternative, you could repeatedly divide the integer by 10, and then rollback one value once you reach zero. Since string operations are generally slow, this may be faster than string manipulation, but is by no means elegant.

Something like this:

while(curr>=10)       curr /= 10;  


Solution:19

start = getFirstDigit(start);     public int getFirstDigit(final int start){      int number = Math.abs(start);      while(number > 10){          number /= 10;      }      return number;  }  

or

public int getFirstDigit(final int start){    return getFirstDigit(Math.abs(start), true);  }  private int getFirstDigit(final int start, final boolean recurse){    if(start < 10){      return start;    }    return getFirstDigit(start / 10, recurse);  }  


Solution:20

int start = curr;  while (start >= 10)    start /= 10;  

This is more efficient than a ToString() approach which internally must implement a similar loop and has to construct (and parse) a string object on the way ...


Solution:21

Very easy method to get the Last digit:

int myInt = 1821;    int lastDigit = myInt - ((myInt/10)*10); // 1821 - 1820 = 1  


Solution:22

This is what I usually do ,please refer my function below :

This function can extract first number occurance from any string you can modify and use this function according to your usage

   public static int GetFirstNumber(this string strInsput)      {          int number = 0;          string strNumber = "";          bool bIsContNo = true;          bool bNoOccued = false;            try          {              var arry = strInsput.ToCharArray(0, strInsput.Length - 1);                foreach (char item in arry)              {                  if (char.IsNumber(item))                  {                      strNumber = strNumber + item.ToString();                        bIsContNo = true;                        bNoOccued = true;                  }                  else                  {                      bIsContNo = false;                  }                    if (bNoOccued && !bIsContNo)                  {                      break;                  }                  }                number = Convert.ToInt32(strNumber);            }          catch (Exception ex)          {                return 0;          }            return number;        }  


Solution:23

Here is a simpler way that does not involve looping

int number = 1234  int firstDigit = Math.Floor(number/(Math.Pow(10, number.ToString().length - 1))  

That would give us 1234/Math.Pow(10, 4 - 1) = 1234/1000 = 1


Solution:24

int i = 4567789;  int digit1 = int.Parse(i.ToString()[0].ToString());  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »