There was little buggy version of Python base conversion around, so here quick hack for my own program, including test with random numbers to verify it.

``````# -*- coding: cp1252 -*-
from random import randint

symbols = '0123456789abcdefghijklmnopqrstuvwxyzÃ¥Ã¤Ã¶'
symbol_values = dict(reversed(v) for v in enumerate(symbols))

def int_to_base(number, base):
if base > len(symbols) or base < 2:
raise ValueError('Invalid base %i' % base)
s = ''
if number < 0:
number, neg = -number, True
else:
neg = False

while number:
number, this = divmod(number, base)
s = symbols[this] + s

return (neg * '-' ) + s

def value_in_base(string, base):
minus = string.lstrip().startswith('-')
v = sum(symbol_values[sym] * base ** power
for power, sym in enumerate(reversed(string.strip(' -'))))
return -v if minus else v

num_check = 100
for count in range(num_check):
num, b = randint(-100000, 10000), randint(2,len(symbols))
print('Original %i' % num)
v = int_to_base(num, b)
print('%s base %i' % (v, b))
print(value_in_base(v, b))
if b < 37:
print('check: %s\n' % int(v, b))
assert int(v, b) == num``````

Specialties:
IT/Science/Contracts/Religious translation/interpreting FIN-ENG-FIN
Python programming

2
Contributors
5
Replies
13
Views
5 Years
Discussion Span
Last Post by pyTony

Original was not really buggy, but was missing base check for other function, so here one slightly improved, with also balanced range for testing, instead of mostly negative:

``````# -*- coding: cp1252 -*-
from random import randint

symbols = '0123456789abcdefghijklmnopqrstuvwxyzåäö'
symbol_values = dict(reversed(v) for v in enumerate(symbols))

def int_to_base(number, base):
if base > len(symbols) or base < 2:
raise ValueError('Invalid base %i' % base)
s = ''
if number < 0:
number, neg = -number, True
else:
neg = False

while number:
number, this = divmod(number, base)
s = symbols[this] + s

return str((neg * '-' ) + s)

def value_in_base(string, base):
if base > len(symbols) or base < 2:
raise ValueError('Invalid base %i' % base)
minus = string.lstrip().startswith('-')
v = sum(symbol_values[sym] * base ** power
for power, sym in enumerate(reversed(string.lower().strip(' -'))))
return -v if minus else v

num_check = 100
for count in range(num_check):
num, b = randint(-10000, 10000), randint(2,len(symbols))
print('\nOriginal %i' % num)
v = int_to_base(num, b)
print('%s base %i' % (v, b))
print(value_in_base(v, b))
assert value_in_base(v, b) == num``````

What is missing is unary coding. Also if all symbols would be defined for UTF-16, big numbers could be printed in UTF-16 in base 65536, otherwise with printable set of 256 letters, numbers binary representation could be easily printed as base 256, one letter per byte.

Edited by pyTony: Spelling

Of course the bug had to be there, if number is 0, the loop is not entered so line 20 must be revised to:

``return str((neg * '-') + s) if s else '0'``

Edited by pyTony: n/a

To be more restrictive on value of the symbols in numbers you can initialize each time the dictionary for acceptable symbols:

``````def value_in_base(string, base):
if base > len(symbols) or base < 2:
raise ValueError('Invalid base %i' % base)
symbol_values = dict(reversed(v) for v in enumerate(symbols[:base]))
minus = string.lstrip().startswith('-')
v = sum(symbol_values[sym] * base ** power
for power, sym in enumerate(reversed(string.lower().lstrip(' -'))))
return -v if minus else v``````

Or you can be satisfied with simple linear search:

``````def value_in_base(string, base):
if base > len(symbols) or base < 2:
raise ValueError('Invalid base %i' % base)
minus = string.lstrip().startswith('-')
string = string.lower().lstrip('-')
assert all(c in symbols[:base] for c in string)
v = sum(symbols.find(sym) * base ** power
for power, sym in enumerate(reversed(string)))
return -v if minus else v``````