9

I would like to know how to do an equivalent of the range function in python, but with the ability to specify the base number. For example:

countUp(start=0, end=1010, base=2)
countUp(start=0, end=101, base=3)
countUp(start=0, end=22, base=4)

Example output for base 2 counting:

[0, 1, 10, 11, 100, ...]

Is there a function I'm missing that does this? Or what could I do instead?

Spooky
  • 1,752
  • 21
  • 37
  • 6
    `0`, `1`, `10`, `11`, is not really base 2 counting. Just *display* the numbers in a different base. You can't produce bases over 10 without letters anyway. – Martijn Pieters Dec 01 '15 at 21:54
  • 1
    you can make your own with a combination of `range` and some sort of [base conversion](http://interactivepython.org/runestone/static/pythonds/Recursion/pythondsConvertinganIntegertoaStringinAnyBase.html) – R Nar Dec 01 '15 at 21:54
  • 2
    Python integers have no base. They're just integers. – user2357112 Dec 01 '15 at 21:58

4 Answers4

9

You are apparently confusing numbers with the representation of numbers.

A number does not have a base... it's the number representation that has a base... for example the number represented as "101" in base 2 is the same as the number represented with "5" in base 10.

The range function will count successive numbers, and you can get their representation in any base you like with something like:

digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

def int2str(x, base):
    if x < 0:
        return "-" + int2str(-x, base)
    return ("" if x < base else int2str(x//base, base)) + digits[x % base]
6502
  • 112,025
  • 15
  • 165
  • 265
3

You can not crate integers with special based, but you can create your expected numbers in a specified base in string :

def my_range(start,end,base,step=1):

    def Convert(n,base):
       string = "0123456789ABCDEF"
       if n < base:
          return string[n]
       else:
          return Convert(n//base,base) + string[n%base]
    return (Convert(i,base) for i in range(start,end,step))

Demo:

print list(my_range(4,20,2))
['100', '101', '110', '111', '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111', '10000', '10001', '10010', '10011']

Note that the passed string string = "0123456789ABCDEF" to function will works till base 16, if want to calculate greater based you can use more letters.

Mazdak
  • 105,000
  • 18
  • 159
  • 188
2

You can do it with a custom iterator:

I took the iterater code from here and the base conversion from here

import string
class BaseRange:
    def __init__(self, low, high, base):
        digs = string.digits + string.letters
        self.current = low
        self.high = high
        self.base = base
    def __iter__(self):
        return self
    def next(self):  # Python 3 requires this to be __next__
        if self.current > self.high:
            raise StopIteration
        else:
            self.current += 1
            return self.int2base(self.current - 1, self.base)
    def int2base(self, x, base):
        if x < 0: sign = -1
        elif x == 0: return digs[0]
        else: sign = 1
        x *= sign
        digits = []
        while x:
            digits.append(digs[x % base])
            x /= base
        if sign < 0:
            digits.append('-')
            digits.reverse()
        return ''.join(digits)

A Few Example runs produces:

>>> for c in BaseRange(0, 10, 2):
    print(c)


0
1
01
11
001
101
011
111
0001
1001
0101
>>> for c in BaseRange(0, 10, 3):
    print(c)


0
1
2
01
11
21
02
12
22
001
101
JawguyChooser
  • 1,816
  • 1
  • 18
  • 32
Brian Cain
  • 946
  • 1
  • 7
  • 20
0

You could do this with the itertools product function.

from itertools import product

def countUp(start, end, base):
    n_digits = len(end)
    combs = product(*[range(base)] * n_digits)
    while (n := next(combs)) <= end:
        yield n

list(countUp(start=0, end=(2, 0), base=3))
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0)]
Bill
  • 10,323
  • 10
  • 62
  • 85