55

I want to check the first two digits of a number in Python. Something like this:

for i in range(1000): if(first two digits of i == 15): print("15") elif(first two digits of i == 16): print("16") 

Is there a command to check the first two digits of a number? I'd like to avoid commands like if(i>149 and i<160):...

4
  • 2
    "first two numbers of a number" -- you mean to say "first two digit of number" ?? Commented Dec 21, 2016 at 20:24
  • 4
    Convert to string and check if first two symbols are "15". Commented Dec 21, 2016 at 20:25
  • Sorry Dinesh Pundkar. Yes I mean the first two digit of number... Commented Dec 21, 2016 at 21:10
  • str(i).startswith(str(15)) or str(i).startswith('15') Commented May 22, 2019 at 1:28

6 Answers 6

110

You can convert your number to string and use list slicing like this:

int(str(number)[:2]) 

Output:

>>> number = 1520 >>> int(str(number)[:2]) 15 

You can turn this into a function to handle edge-cases, such as negative number.

def first_n_digits(num, n): num = abs(num) num_str = str(num) if n >= len(num_str): return num return int(num_str[:n]) 
Sign up to request clarification or add additional context in comments.

3 Comments

I originally came here for a math-based answer, but found this string-based solution is faster than the other math-based answer provided. see %timeit results below
what about rounding number ?
I would assume that a large portion of the math version’s runtime is math.log looking up log in the math module each time. What happens if you replace it with from math import log and call it just as log?
35

Both of the previous 2 answers have at least O(n) time complexity and the string conversion has O(n) space complexity too. Here's a solution for constant time and space:

num // 10 ** (int(math.log(num, 10)) - 1) 

Function:

import math def first_n_digits(num, n): return num // 10 ** (int(math.log(num, 10)) - n + 1) 

Output:

>>> first_n_digits(123456, 1) 1 >>> first_n_digits(123456, 2) 12 >>> first_n_digits(123456, 3) 123 >>> first_n_digits(123456, 4) 1234 >>> first_n_digits(123456, 5) 12345 >>> first_n_digits(123456, 6) 123456 

You will need to add some checks if it's possible that your input number has less digits than you want.

5 Comments

Obviously not since you cannot take logs of negative values. But since we are just looking at digits, just wrap it in np.abs() and then it works.
More importantly, this does not work for e.g. 1000 and 1; first_n_digits(1000,1) returns 10. This method always has problems with digits followed by lots of zeros.
this turns out to be slower than string conversion/list slicing for large N
It's O(logN), not O(n) time and space complexity for string based solutions.
This is O(n) ...
16

Comparing the O(n) time solution with the "constant time" O(1) solution provided in other answers goes to show that if the O(n) algorithm is fast enough, n may have to get very large before it is slower than a slow O(1).

The strings version is approx. 60% faster than the "maths" version for numbers of 20 or fewer digits. They become closer only when then number of digits approaches 200 digits

# the "maths" version import math def first_n_digits1(num, n): return num // 10 ** (int(math.log(num, 10)) - n + 1) %timeit first_n_digits1(34523452452, 2) 1.21 µs ± 75 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) %timeit first_n_digits1(34523452452, 8) 1.24 µs ± 47.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) # 22 digits %timeit first_n_digits1(3423234239472523452452, 2) 1.33 µs ± 59.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) %timeit first_n_digits1(3423234239472523452452, 15) 1.23 µs ± 61.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) # 196 digits %timeit first_n_digits1(3423234239472523409283475908723908723409872390871243908172340987123409871234012089172340987734507612340981344509873123401234670350981234098123140987314509812734091823509871345109871234098172340987125988123452452, 39) 1.86 µs ± 21.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) # The "string" verions def first_n_digits2(num, n): return int(str(num)[:n]) %timeit first_n_digits2(34523452452, 2) 744 ns ± 28.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) %timeit first_n_digits2(34523452452, 8) 768 ns ± 42.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) # 22 digits %timeit first_n_digits2(3423234239472523452452, 2) 767 ns ± 33.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) %timeit first_n_digits2(3423234239472523452452, 15) 830 ns ± 55.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) # 196 digits %timeit first_n_digits2(3423234239472523409283475908723908723409872390871243908098712340987123401208917234098773450761234098134450987312340123467035098123409812314098734091823509871345109871234098172340987125988123452452, 39) 1.87 µs ± 140 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) 

Comments

5

Dom's solution actualy has problems with numbers such as 1000, 1000000 etc.
This is because

>>> math.log(1000, 10) 2.9999999999999996 

(result < 3)
But using math.log10() makes it right. (python 3.8)

>>> math.log10(1000) 3.0 

Perhaps functions log and log10 have different calculation algorithms.

Fixed function is

import math def first_n_digits(num, n): return num // 10 ** (int(math.log10(num)) - n + 1) 

Related: Python math.log and math.log10 giving different results
(I probably should have commented on dom's answer but I don't have enough reputation)

Comments

1

You can use a regular expression to test for a match and capture the first two digits:

import re for i in range(1000): match = re.match(r'(1[56])', str(i)) if match: print(i, 'begins with', match.group(1)) 

The regular expression (1[56]) matches a 1 followed by either a 5 or a 6 and stores the result in the first capturing group.

Output:

15 begins with 15 16 begins with 16 150 begins with 15 151 begins with 15 152 begins with 15 153 begins with 15 154 begins with 15 155 begins with 15 156 begins with 15 157 begins with 15 158 begins with 15 159 begins with 15 160 begins with 16 161 begins with 16 162 begins with 16 163 begins with 16 164 begins with 16 165 begins with 16 166 begins with 16 167 begins with 16 168 begins with 16 169 begins with 16 

1 Comment

Mhm, some people do everything with regex even if it is clearly a huge overkill …
1

'If trying to obtain first 2 digits of a 4 digit number, then you can use the solution below:'

abs(number//100)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.