J'utilise souvent un bc
utilitaire pour convertir hexadécimal en décimal et vice versa. Cependant, il s'agit toujours d'essais et d'erreurs sur la manière ibase
et obase
la configuration. Par exemple ici, je veux convertir la valeur hexadécimale C0 en décimal:
$ echo "ibase=F;obase=A;C0" | bc
180
$ echo "ibase=F;obase=10;C0" | bc
C0
$ echo "ibase=16;obase=A;C0" | bc
192
Quelle est la logique ici? obase
( A
dans mon troisième exemple) doit être dans la même base que la valeur qui est convertie ( C0
dans mes exemples) et ibase
( 16
dans mon troisième exemple) doit être dans la base où je convertis?
Réponses:
Ce que vous voulez vraiment dire, c'est:
pour hex-décimal, et:
pour décimal-hex.
Vous n'avez pas besoin de donner à la fois
ibase
etobase
pour toute conversion impliquant des nombres décimaux, car ces paramètres par défaut sont 10.Vous ne devez donner à la fois pour les conversions telles que binaire à six pans. Dans ce cas, je trouve plus facile de donner un sens aux choses si vous donnez d'
obase
abord:Si vous donnez d'
ibase
abord à la place, cela modifie l'interprétation duobase
paramètre suivant , de sorte que la commande doit être:En effet, dans cet ordre, la
obase
valeur est interprétée comme un nombre binaire, vous devez donc donner 10000₂ = 16 pour obtenir une sortie en hexadécimal. C'est maladroit.Voyons maintenant pourquoi vos trois exemples se comportent comme ils le font.
echo "ibase=F;obase=A;C0" | bc
180
Cela définit la base d'entrée à 15 et la base de sortie à 10, car une valeur à un chiffre est interprétée en hexadécimal, selon POSIX . Cela demande
bc
de vous dire ce que C0₁₅ est dans la base A₁₅ = 10, et il répond correctement à 180₁₀, bien que ce ne soit certainement pas la question que vous vouliez poser.echo "ibase=F;obase=10;C0" | bc
C0
Il s'agit d'une conversion nulle en base 15.
Pourquoi? Tout d'abord, parce que le
F
chiffre unique est interprété en hexadécimal, comme je l'ai souligné dans l'exemple précédent. Mais maintenant que vous l'avez défini sur la base 15, le paramètre de base de sortie suivant est interprété de cette façon, et 10₁₅ = 15, vous avez donc une conversion nulle de C0₁₅ à C0₁₅.C'est vrai, la sortie n'est pas en hexadécimal comme vous le supposiez, elle est en base 15!
Vous pouvez le prouver par vous-même en essayant de convertir
F0
au lieu deC0
. Puisqu'il n'y a pas deF
chiffre dans la base 15,bc
il le serreE0
et donneE0
comme sortie.echo "ibase=16; obase=A; C0"
192
C'est le seul de vos trois exemples qui a probablement une utilité pratique.
Il est en train de changer la base d'entrée à six pans premier , de sorte que vous ne avez plus besoin de creuser dans la spécification Posix de comprendre pourquoi
A
est interprété comme hex, 10 dans ce cas. Le seul problème avec cela est qu'il est redondant de définir la base de sortie sur A₁₆ = 10, car c'est sa valeur par défaut.la source
Le réglage
ibase
signifie que vous devez définirobase
cette même base. Expliquer vos exemples montrera ceci:Vous définissez
bc
de considérer les numéros d'entrée comme représentés dans la base 15 avec le "ibase = F". "obase = A" définit les numéros de sortie à la base 10, qui est la valeur par défaut.bc
lit C0 comme un nombre de base 15: C = 12. 12 * 15 = 180.Dans celui-ci, vous définissez l'entrée sur la base 15 et la sortie sur 10 - dans la base 15, donc la base de sortie est 15. L'entrée C0 dans la base 15 est la sortie C0 dans la base 15.
Réglez l'entrée sur la base 16, la sortie sur la base 10 (A dans la base 16 est 10 dans la base 10).
C0 converti en base 10 est: 12 * 16 = 192
Ma règle personnelle est de définir d'abord obase, afin que je puisse utiliser la base 10. Ensuite, définissez ibase, en utilisant également la base 10.
Notez que
bc
cela a une exception ironique:ibase=A
etobase=A
définit toujours l'entrée et la sortie sur la base 10. Depuis labc
page de manuel:Ce comportement est inscrit dans la spécification de
bc
: à partir de la spécification OpenGroup 2004bc
:C'est pourquoi le
ibase=F
paramètre a changé votre base d'entrée en base 15, et pourquoi j'ai recommandé de toujours définir la base en utilisant la base 10. Évitez de vous embrouiller.la source
Tous les nombres sont interprétés par GNU bc comme la base d'entrée actuelle qui est en vigueur pour l'instruction dans laquelle le nombre apparaît. Lorsque vous utilisez un chiffre en dehors de l'entrée actuelle, interprétez-les comme le chiffre le plus élevé disponible dans la base (9 en décimal) lorsque la partie d'un nombre à plusieurs chiffres, ou comme leurs valeurs normales lorsqu'il est utilisé comme un nombre à un seul chiffre (
A
== 10 en décimal).Dans le manuel GNU bc :
Cependant, vous devez savoir que la norme POSIX ne définit ce comportement que pour les affectations à
ibase
etobase
, et dans aucun autre contexte.De la spécification SUS sur bc :
Le facteur clé qui vous manque est que F n'est pas en fait seize, mais en fait quinze, donc lorsque vous définissez ibase = F, vous définissez la base d'entrée sur quinze.
Par conséquent, pour définir la portably ibase en hexadécimal d'un état inconnu, vous devez donc utiliser deux déclarations:
ibase=A; ibase=16
. Cependant, au début du programme, vous pouvez vous fier à ce qu'il soit décimal et simplement l'utiliseribase=16
.la source
ibase=A; ibase=16
.Il est toujours recommandé de définir
ibase
et d'obase
utiliser un nombre à un chiffre, au lieu d'un nombre tel que16
, car selon labc
page de manuel,Cela signifie que
A,B,...,F
les valeurs ont toujours10,11,...,15
respectivement, quelle que soit la valeur deibase
. Vous pouvez également utiliserF+1
pour spécifier le numéro16
. Par exemple, vous feriez mieux d'écrireau lieu d'écrire
echo "ibase=16; obase=A; C0" | bc
pour spécifier que la base d'entrée est16
et la base de sortie l'est10
. Ou par exemple, si vous voulez les deuxibase
etobase
avoir 16 ans, vous feriez mieux d'utiliserau lieu d'utiliser
ibase=16; obase=10
. De même, si vous allez entrer vos nombres en base 14 et les sortir en base 16, utilisezBien que les formes de bain aient les mêmes résultats, la première est moins sujette aux erreurs, tandis que la seconde peut conduire à plus de confusion et d'erreur.
La différence entre les deux formes devient particulièrement plus apparente lorsque vous êtes dans l'environnement d'exécution de
bc
ou que vous allez écrire vos calculs dans un fichier, puis passer ce fichierbc
en argument. Dans de telles situations, vous devrez peut-être modifier les valeurs deibase
etobase
plusieurs fois, et l'utilisation de ce dernier formulaire peut entraîner de graves confusions et erreurs. (vis-Le)la source