I prefer an approach that uses already implemented algorithms. While many other solutions use recursive divisions by 10 , I think it's better to use logarithms with 10 points that have O(1) complexity, so the complexity of the whole solution is O(1) .
We divide the task into two parts.
The first part will handle the case when number * 10^n is between min and max for at least one n . This would allow us to check, for example, if number = 12 and min,max = 11225,13355 , that x = 12000 = 12*10^3 is between min and max . If this test is checked, it means that the result is True .
The second part will handle cases when number starts with either min or max . For example, if number = 12 and min,max = 12325,14555 , the first test will fail, because 12000 not between min and max (as well as all other numbers 12*10^n for all n ). But the second test will find that 12 is the beginning of 12325 and returns True .
First
Check if the first x = number*10^n , which is equal to or greater than min , is less than or equal to max (so min <= x <= max, where x is number*10^n for any integer n ). If it is greater than max , than all the other x es will be larger, since we took the smallest.
log(number*10^n) > log(min) log(number) + log(10^n) > log(min) log(number) + n > log(min) n > log(min) - log(number) n > log(min/number)
To get the number for comparison, we simply calculate the first satisfactory n :
n = ceil(log(min/number))
And then calculate the number x :
x = number*10^n
Second
We must check whether our number is the literal beginning of any boundary.
We simply compute x , starting with the same digits as number , and padding 0 at the end, having the same length as min :
magnitude = 10**(floor(log10(min)) - floor(log10(number))) x = num*magnitude
And then check if the difference between min and x (on the scale scale) is less than 1 and greater than or equal to 0 :
0 <= (min-x)/magnitude < 1
So if number 121 and min is 132125 , then magnitude is 1000 , x = number*magnitude will be 121000 . min - x gives 132125-121000 = 11125 , which should be less than 1000 (otherwise the start of min would be more than 121 ), so we compare it with magnitude by dividing by this value and comparing with 1 , And that's fine if min - 121000 but not OK if min is 122000 , so 0 <= and < 1 .
The same algorithm for max .
Pseudo code
Including all of this in pseudo-code gives this algorithm:
def check(num,min,max): # num*10^n is between min and max #------------------------------- x = num*10**(ceil(log10(min/num))) if x>=min and x<=max: return True # if num is prefix substring of min #------------------------------- magnitude = 10**(floor(log10(min)) - floor(log10(num))) if 0 <= (min-num*magnitude)/magnitude < 1: return True # if num is prefix substring of max #------------------------------- magnitude = 10**(floor(log10(max)) - floor(log10(num))) if 0 <= (max-num*magnitude)/magnitude < 1: return True return False
This code can be optimized by avoiding the re-calculation of log10(num) . In addition, in the final solution, I would go from float to an integer region ( magnitude = 10**int(floor(log10(max)) - floor(log10(num))) ), and then perform all comparisons without division, i.e. e. 0 <= (max-num*magnitude)/magnitude < 1 β 0 <= max-num*magnitude < magnitude . This would facilitate the possibility of rounding errors.
In addition, it may be possible to replace magnitude = 10**(floor(log10(min)) - floor(log10(num))) with magnitude = 10**(floor(log10(min/num))) , where log10 calculated just one time. But I cannot prove that he will always give the correct results, and I cannot refute it. If anyone could prove it, I would be very grateful.
Tests (in Python): http://ideone.com/N5R2j (you can edit input to add other tests).