sistema que permita para otro llevar float diseñar convertir conversiones conversion codigo cabo binario algoritmo python base radix

que - convertir un string en float python



¿Cómo convertir un entero en cualquier base a una cadena? (23)

¡Excelentes respuestas! Supongo que la respuesta a mi pregunta fue "no". No me faltaba ninguna solución obvia. Aquí está la función que usaré que condensa las buenas ideas expresadas en las respuestas.

  • permitir el mapeo de caracteres proporcionado por el que llama (permite codificar base64)
  • cheques para negativo y cero
  • mapea números complejos en tuplas de cuerdas

def int2base(x,b,alphabet=''0123456789abcdefghijklmnopqrstuvwxyz''): ''convert an integer to its string representation in a given base'' if b<2 or b>len(alphabet): if b==64: # assume base64 rather than raise error alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" else: raise AssertionError("int2base base out of range") if isinstance(x,complex): # return a tuple return ( int2base(x.real,b,alphabet) , int2base(x.imag,b,alphabet) ) if x<=0: if x==0: return alphabet[0] else: return ''-'' + int2base(-x,b,alphabet) # else x is non-negative real rets='''' while x>0: x,idx = divmod(x,b) rets = alphabet[idx] + rets return rets

Python permite la creación fácil de un entero a partir de una cadena de una base dada vía

int(str, base).

Quiero realizar el inverso: creación de una cadena a partir de un entero , es decir, quiero alguna función int2base(num, base) , tal que:

int(int2base(x, b), b) == x

El nombre de función / orden de argumento no es importante.

Para cualquier número x base b que int() aceptará.

Esta es una función fácil de escribir: de hecho, es más fácil que describirla en esta pregunta. Sin embargo, siento que debo estar perdiendo algo.

Sé sobre las funciones bin , oct , hex , pero no puedo usarlas por varias razones:

  • Esas funciones no están disponibles en versiones anteriores de Python, con las cuales necesito compatibilidad con (2.2)

  • Quiero una solución general que pueda llamarse de la misma manera para diferentes bases

  • Quiero permitir bases que no sean 2, 8, 16

Relacionado


Aquí hay una versión recursiva que maneja enteros con signo y dígitos personalizados.

def baseConverter(x, b): s = "" d = string.printable.upper() while x > 0: s += d[x%b] x = x / b return s[::-1]


Hice un paquete de pip para esto.

Te recomiendo que uses mi base.py https://github.com/kamijoutouma/bases.py que fue inspirado por bases.js

def base(decimal ,base) : list = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" other_base = "" while decimal != 0 : other_base = list[decimal % base] + other_base decimal = decimal / base return other_base print base(31 ,16)

consulte https://github.com/kamijoutouma/bases.py#known-basesalphabets para saber qué bases son utilizables

EDITAR: enlace de pip https://pypi.python.org/pypi/bases.py/0.2.2


Las cadenas no son la única opción para representar números: puede usar una lista de enteros para representar el orden de cada dígito. Esos pueden convertirse fácilmente en una cadena.

Ninguna de las respuestas rechaza base <2; y la mayoría funcionará muy lentamente o se bloqueará con desbordamientos de pila para números muy grandes (como 56789 ** 43210). Para evitar tales fallas, reduzca rápidamente así:

DIGITS = "0123456789abcdefghijklmnopqrstuvwxyz" # note that the order of the digits is reversed for digits before the point NO_GROUPING = lambda g: g concat = "".join concat_backwards = lambda g: concat(e for e in reversed(list(g))) def grouping(length = 3, char = ''_''): def yieldor(digits): i = 0 for d in digits: if i == length: yield char i = 0 yield d i+=1 return yieldor class Converter: def __init__(self, baseDigits: (int, str), beforePoint = NO_GROUPING, afterPoint = NO_GROUPING, decimalPoint = ''.'', digitPrecision = 16, trimZeros = True): if isinstance(baseDigits, int): baseDigits = DIGITS[:baseDigits] self.baseDigits = baseDigits self.beforePoint = beforePoint self.afterPoint = afterPoint self.decimalPoint = decimalPoint self.digitPrecision = digitPrecision self.trimZeros = trimZeros def to_string(self, number: (int, float, complex)) -> str: if isinstance(number, complex): if number.imag == 0: return self.to_string(number.real) if number.real == 0: return self.to_string(number.imag) + ''j'' return "({}+{}j)".format(self.to_string(number.real), self.to_string (number.imag)) if number < 0: return ''-'' + self.to_string(-number) digitCount = len(self.baseDigits) if isinstance(number, float): # round correctly precError=digitCount**-self.digitPrecision number+=0.5*precError if self.trimZeros: def yieldor(n): p = precError for i in range(self.digitPrecision): if n <= p: return p *= digitCount n *= digitCount digit = int(n) n -= digit yield self.baseDigits[digit] else: def yieldor(n): for i in range(self.digitPrecision): n *= digitCount digit = int(n) n -= digit yield self.baseDigits[digit] a = concat(self.afterPoint(yieldor(number%1))) return ( self.to_string(int(number)) + (a and self.decimalPoint + a) ) else: #is int if not number: return self.baseDigits[0] def yieldor(n): while n: n, digit = divmod(n, digitCount) yield self.baseDigits[digit] return concat_backwards(self.beforePoint(yieldor(number))) # some tests: if __name__ == "__main__": def conv_test(num, digits, *argv, **kwv): print(num, "->", digits if isinstance(digits, int) else "{} ({})".format(len(digits), digits), Converter(digits, *argv, **kwv).to_string(num)) conv_test(True, "ft") conv_test(123, 12, grouping(2)) conv_test(-0xf00d, 16) conv_test(1000, True<<True, grouping(4)) conv_test(1_000_000, "0+-", beforePoint = grouping(2, ''|'')) conv_test(1.5, 10) conv_test(0.999999999, 10, digitPrecision = 8) conv_test(-0.1, 10) import math conv_test(math.pi, 10, afterPoint = grouping(5, '' '')) conv_test(0.123456789, 10, digitPrecision = 6) grSpc = grouping(1, '' '') conv_test(math.e, ["off", "on"], grSpc, grSpc, " dot ", digitPrecision = 7) conv_test(1 + 1.5j, 10) conv_test(50j, 10) conv_test(10.01, ''-<>'') # and generate some brainfuck-code here: conv_test(1701**42, ''+-<>,.]['', digitPrecision = 32)

Speedwise, n_to_base es comparable con str para grandes cantidades (alrededor de 0.3s en mi máquina), pero si lo comparas contra hex te sorprenderá (aproximadamente 0.3ms en mi máquina, o 1000x más rápido). La razón es porque el entero grande se almacena en la memoria en la base 256 (bytes). Cada byte puede simplemente convertirse en una cadena hexagonal de dos caracteres. Esta alineación solo ocurre para bases que son potencias de dos, por lo que hay casos especiales para 2,8 y 16 (y base64, ascii, utf16, utf32).

Considere el último dígito de una cadena decimal. ¿Cómo se relaciona con la secuencia de bytes que forma su número entero? Etiquetemos los bytes s[i] con s[0] siendo el menos significativo (pequeño endian). Entonces, el último dígito es sum([s[i]*(256**i) % 10 for i in range(n)]) . Bueno, sucede que 256 ** i termina con un 6 para i> 0 (6 * 6 = 36) por lo que el último dígito es (s[0]*5 + sum(s)*6)%10 . A partir de esto, puede ver que el último dígito depende de la suma de todos los bytes. Esta propiedad no local es lo que hace que la conversión a decimal sea más difícil.


No he visto ningún convertidor de flotador aquí. Y me perdí la agrupación por siempre tres dígitos.

QUE HACER:

-números en expresión científica (n.nnnnnn*10**(exp) - el ''10'' es self.baseDigits[1::-1]/self.to_string(len (self.baseDigits))

-from_string-function.

-base 1 -> números romanos?

-ref de complejo con agles

Así que aquí está mi solución:

def bn(x,b,ab="0123456789abcdefghijklmnopqrstuvwxyz..." a = "" while (x>0): x,r = divmod(x,n) a += ab[r] return a[::-1] bn(2**100, 36)


Otra solución, funciona con base 2 a 10, necesita modificación para bases más altas:

n2b(10,2) => ''10100'' int(n2b(10,2),2) => 10

Ejemplo:

import string def base_convert(x, base, digits=None): """Convert integer `x` from base 10 to base `base` using `digits` characters as digits. If `digits` is omitted, it will use decimal digits + lowercase letters + uppercase letters. """ digits = digits or (string.digits + string.ascii_letters) assert 2 <= base <= len(digits), "Unsupported base: {}".format(base) if x == 0: return digits[0] sign = ''-'' if x < 0 else '''' x = abs(x) first_digits = base_convert(x // base, base, digits).lstrip(digits[0]) return sign + first_digits + digits[x % base]


Otro corto (y más fácil de entender, imo):

def int_to_str(n, b, symbols=''0123456789abcdefghijklmnopqrstuvwxyz''): try: return (int_to_str(n/b, b) if n >= b else "") + symbols[n%b] except IndexError: raise ValueError( "The symbols provided are not enough to represent this number in " "this base")

Y con el manejo de excepciones adecuado:

def n2b(n, b): if n == 0: return 0 d = [] while n: d.append(int(n % b)) n /= b return ''''.join(map(str,d[::-1]))


Puede usar baseconv.py: https://github.com/semente/python-baseconv

Uso de muestra:

def base10toN(num,n): """Change a to a base-n number. Up to base-36 is supported without special notation.""" num_rep={10:''a'', 11:''b'', 12:''c'', 13:''d'', 14:''e'', 15:''f'', 16:''g'', 17:''h'', 18:''i'', 19:''j'', 20:''k'', 21:''l'', 22:''m'', 23:''n'', 24:''o'', 25:''p'', 26:''q'', 27:''r'', 28:''s'', 29:''t'', 30:''u'', 31:''v'', 32:''w'', 33:''x'', 34:''y'', 35:''z''} new_num_string='''' current=num while current!=0: remainder=current%n if 36>remainder>9: remainder_string=num_rep[remainder] elif remainder>=36: remainder_string=''(''+str(remainder)+'')'' else: remainder_string=str(remainder) new_num_string=remainder_string+new_num_string current=current/n return new_num_string

Hay algunos convertidores bultin como por ejemplo baseconv.base2 , baseconv.base16 y baseconv.base64 .


Python no tiene una función incorporada para imprimir un entero en una base arbitraria. Tendrás que escribir el tuyo si quieres.


Si necesita compatibilidad con versiones antiguas de Python, puede usar gmpy (que incluye una función de conversión int-to-string rápida y completamente general, y puede gmpy para versiones antiguas como esta; es posible que deba probar lanzamientos anteriores desde los recientes no han sido probados para versiones venerables de Python y GMP, solo recientes), o, para una menor velocidad pero más conveniente, usan el código de Python, por ejemplo, simplemente:

import string digs = string.digits + string.ascii_letters def int2base(x, base): if x < 0: sign = -1 elif x == 0: return digs[0] else: sign = 1 x *= sign digits = [] while x: digits.append(digs[int(x % base)]) x = int(x / base) if sign < 0: digits.append(''-'') digits.reverse() return ''''.join(digits)


Sorprendentemente, las personas solo daban soluciones que se convertían en bases pequeñas (más pequeñas que la longitud del alfabeto inglés). No hubo ningún intento de dar una solución que convierta a cualquier base arbitraria de 2 a infinito.

Entonces, aquí hay una solución súper simple:

def numberToBase(n, b): if n == 0: return [0] digits = [] while n: digits.append(int(n % b)) n /= b # //= for python 3 return digits[::-1]

así que si necesitas convertir un número súper enorme a la base 577 ,

numberToBase(67854 ** 15 - 102, 577) , le dará una solución correcta: [4, 473, 131, 96, 431, 285, 524, 486, 28, 23, 16, 82, 292, 538, 149, 25, 41, 483, 100, 517, 131, 28, 0, 435, 197, 264, 455] ,

Que luego puedes convertir a cualquier base que quieras


Una solución recursiva para los interesados. Por supuesto, esto no funcionará con valores binarios negativos. Debería implementar el complemento de Two.

def int2base(a, base, numerals="0123456789abcdefghijklmnopqrstuvwxyz"): baseit = lambda a=a, b=base: (not a) and numerals[0] or baseit(a-a%b,b*base)+numerals[a%b%(base-1) or (a%b) and (base-1)] return baseit()


http://code.activestate.com/recipes/65212/

def baseconvert(n, base): """convert positive decimal integer n to equivalent in another base (2-36)""" digits = "0123456789abcdefghijklmnopqrstuvwxyz" try: n = int(n) base = int(base) except: return "" if n < 0 or base < 2 or base > 36: return "" s = "" while 1: r = n % base s = digits[r] + s n = n / base if n == 0: break return s

Aquí hay otro del mismo enlace

from bases import Bases bases = Bases() bases.toBase16(200) // => ''c8'' bases.toBase(200, 16) // => ''c8'' bases.toBase62(99999) // => ''q0T'' bases.toBase(200, 62) // => ''q0T'' bases.toAlphabet(300, ''aAbBcC'') // => ''Abba'' bases.fromBase16(''c8'') // => 200 bases.fromBase(''c8'', 16) // => 200 bases.fromBase62(''q0T'') // => 99999 bases.fromBase(''q0T'', 62) // => 99999 bases.fromAlphabet(''Abba'', ''aAbBcC'') // => 300


Python doesn''t have a built-in function for printing an integer in an arbitrary base. You''ll have to write your own if you want to.


You could use baseconv.py: https://github.com/semente/python-baseconv

Sample usage:

>>> from baseconv import BaseConverter >>> base20 = BaseConverter(''0123456789abcdefghij'') >>> base20.encode(1234) ''31e'' >>> base20.decode(''31e'') ''1234'' >>> base20.encode(-1234) ''-31e'' >>> base20.decode(''-31e'') ''-1234'' >>> base11 = BaseConverter(''0123456789-'', sign=''$'') >>> base11.encode(''$1234'') ''$-22'' >>> base11.decode(''$-22'') ''$1234''


def baseN(num,b,numerals="0123456789abcdefghijklmnopqrstuvwxyz"): return ((num == 0) and numerals[0]) or (baseN(num // b, b, numerals).lstrip(numerals[0]) + numerals[num % b])

ref: http://code.activestate.com/recipes/65212/

Tenga en cuenta que esto puede conducir a

RuntimeError: maximum recursion depth exceeded in cmp

para enteros muy grandes.


"{0:b}".format(100) # bin: 1100100 "{0:x}".format(100) # hex: 64 "{0:o}".format(100) # oct: 144


>>> import string >>> def int2base(integer, base): if not integer: return ''0'' sign = 1 if integer > 0 else -1 alphanum = string.digits + string.ascii_lowercase nums = alphanum[:base] res = '''' integer *= sign while integer: integer, mod = divmod(integer, base) res += nums[mod] return ('''' if sign == 1 else ''-'') + res[::-1] >>> int2base(-15645, 23) ''-16d5'' >>> int2base(213, 21) ''a3''

salida:

"1F"


3ewfdnca0n6ld1ggvfgg

salida:

3ewfdnca0n6ld1ggvfgg

para convertir a cualquier base, inversa también es fácil.


def dec_to_radix(input, to_radix=2, power=None): if not isinstance(input, int): raise TypeError(''Not an integer!'') elif power is None: power = 1 if input == 0: return 0 else: remainder = input % to_radix**power digit = str(int(remainder/to_radix**(power-1))) return int(str(dec_to_radix(input-remainder, to_radix, power+1)) + digit) def radix_to_dec(input, from_radix): if not isinstance(input, int): raise TypeError(''Not an integer!'') return sum(int(digit)*(from_radix**power) for power, digit in enumerate(str(input)[::-1])) def radix_to_radix(input, from_radix=10, to_radix=2, power=None): dec = radix_to_dec(input, from_radix) return dec_to_radix(dec, to_radix, power)

explicación

En cualquier base, cada número es igual a a1+a2*base**2+a3*base**3... La "misión" es encontrar todos a ''s.

Para cada N=1,2,3... el código está aislando la aN*base**N por "mouduling" por b para b=base**(N+1) que corta todas las a ''s mayores que N, y cortando todas las a''s que su serie es más pequeña que N disminuyendo cada vez que el func sea llamado por la aN*base**N actual aN*base**N

Base% (base-1) == 1 por lo tanto base ** p% (base-1) == 1 y por lo tanto q * base ^ p% (base-1) == q con solo una excepción cuando q = base-1 que devuelve 0. Para arreglar eso en caso de que devuelva 0, el func está comprobando si es 0 desde el principio.

ventajas

en esta muestra hay solo una multiplicación (en lugar de división) y algunos moudulueses que relativamente toman pequeñas cantidades de tiempo.


def generateBase36Alphabet(): return ''''.join([str(i) for i in range(10)]+[chr(i+65) for i in range(26)]) def generateAlphabet(base): return generateBase36Alphabet()[:base] def intToStr(n, base, alphabet): def toStr(n, base, alphabet): return alphabet[n] if n < base else toStr(n//base,base,alphabet) + alphabet[n%base] return (''-'' if n < 0 else '''') + toStr(abs(n), base, alphabet) print(''{} -> {}''.format(-31, intToStr(-31, 16, generateAlphabet(16)))) # -31 -> -1F


def int_to_str(n, b, symbols=''0123456789abcdefghijklmnopqrstuvwxyz''): return (int_to_str(n/b, b, symbols) if n >= b else "") + symbols[n%b]


def n_to_base(n, b): if b < 2: raise # invalid base if abs(n) < b: return [n] ret = [y for d in n_to_base(n, b*b) for y in divmod(d, b)] return ret[1:] if ret[0] == 0 else ret # remove leading zeros def base_to_n(v, b): h = len(v) // 2 if h == 0: return v[0] return base_to_n(v[:-h], b) * (b**h) + base_to_n(v[-h:], b) assert ''''.join([''0123456789''[x] for x in n_to_base(56789**43210,10)])==str(56789**43210)