0

Buen dia , tengo un problema con el siguiente codigo de typeError , pero no entiendo que podria estar mal , si me pudieran ayudar a corregirlo y decirme que tenia mal , Gracias.

if __name__ == '__main__':
    print("Escriba un numero Entero para pasarlo a Hexadecimal")
    num = input()
    x = num
    while True:
        if x%16>9 and x%16<16:
            if x%16==10:
                acum = "A"+acum
            if x%16==11:
                acum = "B"+acum
            if x%16==12:
                acum = "C"+acum
            if x%16==13:
                acum = "D"+acum
            if x%16==14:
                acum = "E"+acum
            if x%16==15:
                acum = "F"+acum
        else:
            acum = str(x%16)+acum
        x = int(x/16)
        if x<=1: break
    if x>0:
        acum = str(x)+acum
    print(num," Decimal = ",acum," en Hexadecimal")
FJSevilla
  • 55,603
  • 7
  • 35
  • 58

1 Answers1

1

¿Qué causa el error?

En concreto, el error es:

TypeError: not all arguments converted during string formatting

La causa es que input en Python 3 retorna siempre una cadena (str). En Python 2 puede retornar un entero, pero jamás debe usarse para entradas de usuario por norma general, para mayor aclaración ver:

Al ser num una cadena (y por tanto x también ya que ambas variables quedan asociadas al mismo objeto str), al intentar calcular el resto de la divisón en la linea:

if x%16>9 and x%16<16:

el operador % no se interpreta como el operador módulo, sino como el viejo operador de formateo de cadenas. Como nuestra cadena no tiene dianas de reemplazo tenemos el error mostrado:

>>> x = "Hola %s"
>>> x % "mundo"
'Hola mundo'

>>> x = "Hola"
>>> x % "mundo"

Traceback (most recent call last):
  File "<ipython-input>", line 1, in <module>
    x % "mundo"
  TypeError: not all arguments converted during string formatting

La solución es simplemente convertir la cadena a entero previamente:

num = int(input())

Además de este problema, al menos en el código que muestras, no defines acum antes del while. Si no lo haces, en cuanto intentes usar la variable en el ciclo tendrás un error:

NameError: name 'acum' is not defined

Por lo tanto, antes del ciclo debes definir la variable:

acum = ""

Dicho esto, unas cuantas observaciones sobre el código:

  • Calculas repetidamente el módulo, sería más eficiente si lo calculas una sola vez y lo asignas a una variable. Es más, en vez de calcular el resto y el cociente por separado, es mucho más simple y eficiente si usas divmod que te retorna ambos.

  • No debes encadenar los if, usa if-elif-else. Al usa if, siempre se evalúan todos,lo cual es muy ineficiente cuando sabemos que en cuanto uno se cierto el resto no lo es. Si usas elif en el momento que el if o un elif sea evaluado como verdadero el resto no se evalúa.

  • Concatenar cadenas en Python es una operación muy ineficiente porque son objetos inmutables. Cada vez que concatenas se crea un nuevo objeto. Es generalmente más eficiente en estos casos usar un contenedor como una lista y luego construir la cadena con str.join.

  • La comparación if x%16>9 and x%16<16: no tiene mucho sentido. Por el propio concepto del módulo, x % 16 siempre va a ser menor que 16. Si tuviera sentido, eso se puede escribir de forma más legible y eficiente como:

    if 9 < x%16 < 16:`
    

Con todo ello en cuenta, una versión alternativa a tu código usando el mismo algoritmo básico sería:

num = int(input("Escriba un numero Entero para pasarlo a Hexadecimal\n"))
if num == 0:
    acum = "0"

else:
    x = num
    acum = []
    while x:
        x, mod = divmod(x, 16)
        if mod > 9:
            if mod == 10:
                acum.append("A")
            elif mod == 11:
                acum.append("B")
            elif mod == 12:
                acum.append("C")
            elif mod == 13:
                acum.append("D")
            elif mod == 14:
                acum.append("E")
            else:
                acum.append("F")
        else:
            acum.append(str(mod))
    acum = "".join(reversed(acum))

print(f"{num} Decimal = {acum} en Hexadecimal")

Aunque supongo que no es el objetivo, se puede obtener el resultado deseado usando el builtin hex:

num = int(input("Escriba un numero Entero para pasarlo a Hexadecimal\n"))
print(f"{num} Decimal = {hex(num)[2:].upper()} en Hexadecimal")
FJSevilla
  • 55,603
  • 7
  • 35
  • 58