Często używam bc
narzędzia do konwersji szesnastkowej na dziesiętną i odwrotnie. Jednak zawsze jest trochę prób i błędów, jak ibase
i obase
należy skonfigurować. Na przykład tutaj chcę przekonwertować wartość szesnastkową C0 na dziesiętną:
$ echo "ibase=F;obase=A;C0" | bc
180
$ echo "ibase=F;obase=10;C0" | bc
C0
$ echo "ibase=16;obase=A;C0" | bc
192
Jaka jest tutaj logika? obase
( A
w moim trzecim przykładzie) musi znajdować się w tej samej bazie, co wartość, która jest konwertowana ( C0
w moich przykładach), a ibase
( 16
w moim trzecim przykładzie) musi znajdować się w bazie, na którą dokonuję konwersji?
Odpowiedzi:
To, co naprawdę chcesz powiedzieć, to:
dla liczby szesnastkowej i dziesiętnej oraz:
dla dziesiętnego na szesnastkowy.
Nie musisz podawać zarówno, jak
ibase
iobase
żadnej konwersji z liczbami dziesiętnymi, ponieważ te ustawienia domyślnie wynoszą 10.Ci nie muszą dać zarówno dla konwersji, takich jak binarny do hex. W takim przypadku uważam, że najłatwiej zrozumieć sens, jeśli podasz
obase
najpierw:Jeśli
ibase
zamiast tego podasz pierwszy, zmienia to interpretację następującegoobase
ustawienia, więc polecenie musi być:Wynika to z tego, że w tej kolejności
obase
wartość jest interpretowana jako liczba binarna, więc musisz podać 10000₂ = 16, aby uzyskać wynik w postaci szesnastkowej. To niezręczne.Teraz zastanówmy się, dlaczego twoje trzy przykłady zachowują się tak, jak one.
echo "ibase=F;obase=A;C0" | bc
180
To ustawia podstawę wejściową na 15, a bazę wyjściową na 10, ponieważ wartość jednocyfrowa jest interpretowana w systemie szesnastkowym, zgodnie z POSIX . To prosi,
bc
aby powiedzieć ci, co C0₁₅ znajduje się w podstawie A₁₅ = 10 i odpowiada poprawnie 180₁₀, chociaż z pewnością nie jest to pytanie, które chciałeś zadać.echo "ibase=F;obase=10;C0" | bc
C0
Jest to konwersja zerowa w bazie 15.
Czemu? Po pierwsze, ponieważ pojedyncza
F
cyfra jest interpretowana szesnastkowo, jak wskazałem w poprzednim przykładzie. Ale teraz, gdy ustawiłeś go na bazę 15, następujące ustawienie wyjściowej bazy jest interpretowane w ten sposób, a 10₁₅ = 15, więc masz konwersję zerową z C0₁₅ na C0₁₅.Zgadza się, dane wyjściowe nie są szesnastkowe, jak zakładałeś, są w bazie 15!
Możesz to sobie udowodnić, próbując przekonwertować
F0
zamiastC0
. PonieważF
w podstawie 15 nie ma cyfry,bc
zaciska jąE0
i podajeE0
jako wynik.echo "ibase=16; obase=A; C0"
192
To jedyny z trzech przykładów, który prawdopodobnie ma praktyczne zastosowanie.
Najpierw zmienia bazę wejściową na heksadecymalną , dzięki czemu nie trzeba już zagłębiać się w specyfikację POSIX, aby zrozumieć, dlaczego
A
w tym przypadku interpretowana jest jako hex, 10. Jedynym problemem jest to, że zbędne jest ustawienie bazy wyjściowej na A = 10, ponieważ jest to jej wartość domyślna.źródło
Ustawienie
ibase
oznacza, że musisz ustawićobase
w tej samej bazie. Wyjaśnienie przykładów pokaże to:Ustawiono
bc
rozpatrywanie liczb wejściowych przedstawionych w podstawie 15 za pomocą „ibase = F”. „obase = A” ustawia liczby wyjściowe na podstawową 10, co jest wartością domyślną.bc
odczytuje C0 jako liczbę podstawową 15: C = 12. 12 * 15 = 180.W tym ustawiasz wejście na bazę 15, a wyjście na 10 - w podstawie 15, więc podstawa wyjścia wynosi 15. Wejście C0 w bazie 15 to wyjście C0 w bazie 15.
Ustaw wejście na bazę 16, wyjście na bazę 10 (A w bazie 16 to 10 w bazie 10).
C0 przeliczone na podstawę 10 wynosi: 12 * 16 = 192
Moją osobistą zasadą jest ustawienie najpierw obase, aby móc korzystać z bazy 10. Następnie ustaw ibase, również używając bazy 10.
Zauważ, że
bc
ma ironiczny wyjątek:ibase=A
iobase=A
zawsze ustawia wejście i wyjście na bazę 10. Ze strony podręcznikabc
:To zachowanie jest zapisane w specyfikacji
bc
: Ze specyfikacji OpenGroup 2004bc
:Dlatego
ibase=F
ustawienie zmieniło bazę wejściową na bazę 15 i dlatego zalecałem, aby zawsze ustawiać bazę za pomocą bazy 10. Unikaj mylenia siebie.źródło
Wszystkie liczby są interpretowane przez GNU bc jako bieżąca podstawa wejściowa, która obowiązuje dla instrukcji, w której pojawia się liczba. Gdy użyjesz cyfry poza bieżącym wejściem, zinterpretuj je jako najwyższą cyfrę dostępną w bazie (9 dziesiętnie), gdy część liczby wielocyfrowej lub ich wartości normalnych, gdy jest stosowany jako liczba jednocyfrowa (
A
== 10 miejsc po przecinku).Z podręcznika GNU bc :
Należy jednak mieć świadomość, że standard POSIX definiuje tylko to zachowanie dla przypisania do
ibase
iobase
, a nie w jakimkolwiek innym kontekście.Ze specyfikacji SUS na bc :
Kluczowym czynnikiem, którego brakuje, jest to, że F nie ma szesnastu, ale tak naprawdę piętnaście, więc kiedy ustawiasz ibase = F, ustawiasz bazę wejściową na piętnaście.
Dlatego, aby przenośnie ustawić ibase do szesnastkowym z nieznanego stanu, dlatego trzeba używać dwa oświadczenia:
ibase=A; ibase=16
. Jednak na początku programu można polegać na systemie dziesiętnym i po prostu go używaćibase=16
.źródło
ibase=A; ibase=16
.Zawsze zaleca się ustawienie
ibase
iobase
używanie liczby jednocyfrowej zamiast liczby takiej jak16
, ponieważ zgodnie zebc
stroną podręcznika,Oznacza to, że
A,B,...,F
zawsze mają10,11,...,15
odpowiednio wartości , niezależnie od wartościibase
. Możesz także użyćF+1
do podania liczby16
. Na przykład lepiej piszzamiast pisać,
echo "ibase=16; obase=A; C0" | bc
aby określić, że podstawa wejściowa jest,16
a wyjściowa podstawa to10
. Lub, na przykład, jeśli chcesz mieć obaibase
iobase
mieć 16 lat, lepiej użyjzamiast używać
ibase=16; obase=10
. Podobnie, jeśli zamierzasz wprowadzić swoje liczby w bazie 14 i wyprowadzić je w bazie 16, użyjChociaż formy kąpieli mają takie same wyniki, te pierwsze są mniej podatne na błędy, podczas gdy te drugie mogą prowadzić do większego zamieszania i błędów.
Różnica między tymi dwiema postaciami staje się bardziej widoczna, gdy jesteś w środowisku wykonawczym
bc
lub zamierzasz zapisać swoje obliczenia w pliku, a następnie przekazać ten plikbc
jako argument. W takich sytuacjach może trzeba zmienić wartościibase
iobase
kilka razy, i za pomocą tej ostatniej formy, może prowadzić do poważnych nieporozumień i błędów. (Doświadcz tego)źródło