A menudo uso la bc
utilidad para convertir hexadecimal a decimal y viceversa. Sin embargo, siempre es un poco de prueba y error cómo ibase
y obase
debe configurarse. Por ejemplo, aquí quiero convertir el valor hexadecimal C0 a decimal:
$ echo "ibase=F;obase=A;C0" | bc
180
$ echo "ibase=F;obase=10;C0" | bc
C0
$ echo "ibase=16;obase=A;C0" | bc
192
¿Cuál es la lógica aquí? obase
( A
en mi tercer ejemplo) debe estar en la misma base que el valor que se convierte ( C0
en mis ejemplos) y ibase
( 16
en mi tercer ejemplo) debe estar en la base a la que me estoy convirtiendo.
Respuestas:
Lo que realmente quieres decir es:
para hexadecimal a decimal y:
para decimal a hexadecimal.
No necesita dar ambas
ibase
yobase
para cualquier conversión que implique números decimales, ya que esta configuración predeterminada es 10.Usted no necesita dar tanto para las conversiones, como binario-a-hexadecimal. En ese caso, me resulta más fácil entender las cosas si das
obase
primero:Si da
ibase
primero, cambia la interpretación de la siguienteobase
configuración, por lo que el comando debe ser:Esto se debe a que en este orden, el
obase
valor se interpreta como un número binario, por lo que debe dar 10000₂ = 16 para obtener la salida en hexadecimal. Eso es torpe.Ahora veamos por qué sus tres ejemplos se comportan como lo hacen.
echo "ibase=F;obase=A;C0" | bc
180
Eso establece la base de entrada en 15 y la base de salida en 10, ya que un valor de un solo dígito se interpreta en hexadecimal, de acuerdo con POSIX . Esto le pide
bc
que le diga qué C0₁₅ está en la base A₁₅ = 10, y está respondiendo correctamente 180₁₀, aunque ciertamente esta no es la pregunta que quería hacer.echo "ibase=F;obase=10;C0" | bc
C0
Esta es una conversión nula en la base 15.
¿Por qué? Primero, porque el único
F
dígito se interpreta en hexadecimal, como señalé en el ejemplo anterior. Pero ahora que lo configuró en base 15, la siguiente configuración base de salida se interpreta de esa manera, y 10₁₅ = 15, por lo que tiene una conversión nula de C0₁₅ a C0₁₅.Así es, la salida no está en hexadecimal como suponías, ¡está en la base 15!
Puedes probarte esto a ti mismo intentando convertir en
F0
lugar deC0
. Como no hay unF
dígito en la base 15,bc
sujételoE0
y daE0
como salida.echo "ibase=16; obase=A; C0"
192
Este es el único de sus tres ejemplos que probablemente tenga algún uso práctico.
Está cambiando la base de entrada a hexadecimal primero , de modo que ya no hay necesidad de cavar en la especificación POSIX de entender por qué
A
se interpreta como hexagonal, 10 en este caso. El único problema es que es redundante establecer la base de salida en A₁₆ = 10, ya que ese es su valor predeterminado.fuente
Configuración
ibase
significa que necesita establecerobase
en esa misma base. Explicar sus ejemplos mostrará esto:Establece
bc
considerar los números de entrada como se representa en la base 15 con el "ibase = F". "obase = A" establece los números de salida en base 10, que es el valor predeterminado.bc
lee C0 como un número base 15: C = 12. 12 * 15 = 180.En este, establece la entrada en la base 15 y la salida en 10, en la base 15, por lo que la base de salida es 15. La entrada C0 en la base 15 es la salida C0 en la base 15.
Establezca la entrada en la base 16, la salida en la base 10 (A en la base 16 es 10 en la base 10).
C0 convertido a base 10 es: 12 * 16 = 192
Mi regla personal es establecer obase primero, para que pueda usar la base 10. Luego establezca ibase, también usando la base 10.
Tenga en cuenta que
bc
tiene una excepción irónica:ibase=A
yobase=A
siempre establece la entrada y la salida en la base 10. Desde labc
página del manual:Este comportamiento está consagrado en la especificación de
bc
: De la especificación OpenGroup 2004bc
:Es por eso que la
ibase=F
configuración cambió su base de entrada a la base 15, y por eso recomendé establecer siempre la base usando la base 10. Evite confundirse.fuente
GNU bc interpreta todos los números como la base de entrada actual que está vigente para la declaración en la que aparece el número. Cuando use un dígito fuera de la entrada actual, inténtelos como el dígito más alto disponible en la base (9 en decimal) cuando parte de un número de varios dígitos, o como sus valores normales cuando se usa como un número de un solo dígito (
A
== 10 en decimal).Del manual de GNU bc :
Sin embargo, debe tener en cuenta que el estándar POSIX sólo define este comportamiento para las asignaciones a
ibase
yobase
, y no en cualquier otro contexto.De la especificación SUS en bc :
El factor clave que falta es que F no es de hecho dieciséis, pero en realidad es quince, por lo que cuando configura ibase = F está configurando la base de entrada en quince.
Por lo tanto, para establecer la forma portable ibase a hexadecimal de un estado desconocido, que por lo tanto es necesario utilizar dos declaraciones:
ibase=A; ibase=16
. Sin embargo, al comienzo del programa puede confiar en que sea decimal y simplemente usarloibase=16
.fuente
ibase=A; ibase=16
.Siempre se recomienda establecer
ibase
yobase
usar un número de un solo dígito, en lugar de un número como16
, ya que, según labc
página del manual,Esto significa que
A,B,...,F
siempre tienen los valores10,11,...,15
respectivamente, independientemente de cuál sea el valor deibase
. También puede usarF+1
para especificar el número16
. Por ejemplo, será mejor que escribasen lugar de escribir
echo "ibase=16; obase=A; C0" | bc
para especificar que la base de entrada es16
y la base de salida es10
. O, por ejemplo, si quiere ambosibase
yobase
tener 16 años, será mejor que useen lugar de utilizar
ibase=16; obase=10
. Del mismo modo, si va a ingresar sus números en la base 14 y generarlos en la base 16, useAunque las formas de baño tienen los mismos resultados, la primera es menos propensa a errores, mientras que la segunda puede generar más confusión y error.
La diferencia entre las dos formas se hace especialmente más evidente cuando estás en el entorno de ejecución de
bc
, o vas a escribir tus cálculos en un archivo, y luego pasar ese archivobc
como argumento. En tales situaciones, es posible que tenga que cambiar los valoresibase
yobase
varias veces, y el uso de esta última forma puede generar graves confusiones y errores. (experimentalo)fuente