Matematyka związana z konwersją z dowolnej bazy na dowolną bazę bez przechodzenia przez bazę 10?

36

Patrzyłem na matematykę dotyczącą konwersji z dowolnej bazy na dowolną bazę. Chodzi bardziej o potwierdzenie moich wyników niż cokolwiek innego. Znalazłem moją odpowiedź na mathforum.org, ale nadal nie jestem pewien, czy mam rację. Mam konwersję z większej bazy na mniejszą bazę w porządku, ponieważ jest to po prostu pierwsza cyfra pomnożona przez bazę, którą chcesz dodać kolejną cyfrę. Mój problem pojawia się podczas konwersji z mniejszej bazy na większą. Robiąc to, rozmawiają o tym, jak trzeba przekonwertować większą bazę, którą chcesz, na mniejszą. Przykładem może być przejście z bazy 4 na bazę 6, w której musisz przekonwertować liczbę 6 na bazę 4, uzyskując 12. Następnie robisz to samo, co podczas konwersji z dużej na małą. Trudność z tym jest taka, że ​​wydaje się, że musisz wiedzieć, co jest jedną liczbą w drugiej bazie. Chciałbym więc wiedzieć, co to jest 6 w bazie 4. Stwarza to duży problem w mojej głowie, ponieważ wtedy potrzebowałbym stołu. Czy ktoś wie, jak to zrobić w lepszy sposób?

Myślałem, że podstawowa konwersja pomoże, ale nie mogę znaleźć żadnej takiej pracy. I ze strony, którą znalazłem, wydaje się, że pozwala ci na konwersję z bazy na bazę bez przechodzenia przez bazę 10, ale najpierw musisz wiedzieć, jak przekonwertować pierwszą liczbę z bazy na bazę. To sprawia, że ​​jest to trochę bezcelowe.

Komentatorzy mówią, że muszę być w stanie przekonwertować literę na liczbę. Jeśli tak, to już to wiem. To jednak nie mój problem. Mój problem polega na przekonwertowaniu dużej bazy na małą bazę. Najpierw muszę przekonwertować numer bazy, który mam, na numer bazy, który chcę. Robiąc to, pokonałem cel, ponieważ jeśli mam możliwość konwersji tych baz na inne, już rozwiązałem swój problem.

Edycja: Zorientowałem się, jak przekonwertować z baz mniejszych lub równych 10 na inne bazy mniejsze lub równe 10. Mogę również przejść z bazy większej niż 10 na dowolną bazę, która ma 10 lub mniej. Problem zaczyna się, gdy konwertujesz z podstawy większej niż 10 na inną bazę większą niż 10. Lub przechodząc z bazy mniejszej niż 10 do bazy większej niż 10. Nie potrzebuję kodu, potrzebuję tylko podstawowej matematyki, która może być zastosowane do kodu.

Nowicjusz
źródło
1
Czy to pytanie dotyczy tego forum?
Andrej Bauer,
2
Procedura jest trywialna, o ile można dodawać i zwielokrotniać w bazie docelowej. Jeśli nie możesz, nie sądzę, że to możliwe.
Karolis Juodelė
9
Griffinowi należy najpierw powiedzieć, co wielu uczniów musi usłyszeć: liczby istnieją bez reprezentacji w bazie . Odpowiedź jest jasna: potrzebujemy algorytmów, jednego do konwertowania reprezentacji liczby w danej bazie na liczbę (czyli czegoś, co przyjmuje stringa zwraca an int), oraz algorytmu, który przyjmuje liczbę i zwraca jej reprezentację w danej bazie.
Andrej Bauer,
1
@AndrejBauer Pytanie dotyczy CS: nawet jeśli nie jest sformułowane w ten sposób, jest to pytanie o algorytm do konwersji między reprezentacjami liczb. [Niepowiązana uwaga: usunąłem kilka mylących komentarzy. Gryf: edytuj pytanie, aby je zaktualizować. Inni: weź to na czacie .]
Gilles „SO- przestań być zły”
1
@ Gryf minęło sporo czasu od twojego pierwotnego pytania. Mam nadzieję, że znalazłeś swoją odpowiedź. Jeśli tak, może warto zaktualizować i zaakceptować odpowiedź lub opublikować swoją. W międzyczasie znalazłem kilka bardzo fajnych pomysłów (mówiących o implementacji w C ++) w archiwach Google Code Jam. Niektóre rozwiązania tego problemu są bardzo kreatywne code.google.com/codejam/contest/32003/dashboard
IsaacCisneros

Odpowiedzi:

45

Wydaje mi się to bardzo podstawowym pytaniem, więc przepraszam, jeśli trochę was nauczę. Najważniejszą rzeczą, którą musisz się tutaj nauczyć, jest to, że liczba nie jest jej cyfrową reprezentacją . Liczba jest abstrakcyjnym obiektem matematycznym, podczas gdy jej cyfrowa reprezentacja jest czymś konkretnym, mianowicie sekwencją symboli na papierze (lub sekwencją bitów w pamięci obliczeniowej lub sekwencją dźwięków, które wydajesz, gdy podajesz liczbę). Mylące jest to, że nigdy nie widzisz liczby, ale zawsze jej cyfrowa reprezentacja. W rezultacie myślisz, że liczba jest reprezentacją.

Dlatego poprawnym pytaniem jest nie „jak przekonwertować z jednej bazy na drugą”, ale „jak dowiedzieć się, która liczba jest reprezentowana przez dany ciąg cyfr” i „jak znaleźć cyfrową reprezentację podany numer ”.

Stwórzmy więc dwie funkcje w Pythonie, jedną do konwersji cyfrowej reprezentacji na liczbę, a drugą do odwrotnego działania. Uwaga: kiedy uruchomimy funkcję, Python wydrukuje oczywiście na ekranie liczbę, którą otrzymał w bazie 10. Ale to nie znaczy, że komputer zachowuje liczby w bazie 10 (nie jest). Nie ma znaczenia, w jaki sposób komputer reprezentuje liczby.

def toDigits(n, b):
    """Convert a positive number n to its digit representation in base b."""
    digits = []
    while n > 0:
        digits.insert(0, n % b)
        n  = n // b
    return digits

def fromDigits(digits, b):
    """Compute the number given by digits in base b."""
    n = 0
    for d in digits:
        n = b * n + d
    return n

Przetestujmy te:

>>> toDigits(42, 2)
[1, 0, 1, 0, 1, 0]
>>> toDigits(42, 3)
[1, 1, 2, 0]
>>> fromDigits([1,1,2,0],3)
42

Uzbrojony w funkcje konwersji problem można łatwo rozwiązać:

def convertBase(digits, b, c):
    """Convert the digits representation of a number from base b to base c."""
    return toDigits(fromDigits(digits, b), c)

Test:

>>> convertBase([1,1,2,0], 3, 2) 
[1, 0, 1, 0, 1, 0]

Uwaga: my nie przechodzą przez podstawę 10 reprezentacji! Przekształciliśmy bazę na liczbę, a następnie liczbę na bazę c . Numer byłbdo nie reprezentowany. (Właściwie tak było, komputer musiał jakoś to reprezentować, i reprezentował to za pomocą sygnałów elektrycznych i funky, które zdarzają się w układach scalonych, ale z pewnością nie były to 0 i 1).

Andrej Bauer
źródło
4
Nie przekonuje mnie to w 100%. W rzeczywistości przekonwertowałeś liczbę na pewną reprezentację (chociaż możesz twierdzić, że nie wiesz, co to jest), ponieważ komputery nie są matematykami platonicznymi, a twój algorytm nie może przekonwertować dowolnej sekwencji cyfr w bazie na bazę b 2 ; może konwertować tylko sekwencje reprezentowane przez konkretną maszynę. Python jest uroczo elastyczny; C nie byłby tak wyrozumiały. Zupełnie słuszne jest pytanie, jak przekonwertować dowolne ciągi z b 1 na b 2 ; jest to jednak możliwe tylko w czasie liniowym, z wyjątkiem niektórych kombinacji zasad (np. 2 <-> 16)b1b2b1b2
rici
1
Warto zadać pytanie, ale aby znaleźć właściwą odpowiedź, najlepiej mieć świadomość faktu, że liczby są bytami abstrakcyjnymi.
Andrej Bauer,
2
Liczba ta przechodzi przez reprezentację podstawy 10, ponieważ fromDigitszwraca liczbę w podstawie 10.
apnorton
8
@anorton: Nie, zdecydowanie nie . Python drukuje liczbę na ekranie w podstawowej 10-cyfrowej reprezentacji, ale sam numer nie jest zapisywany w ten sposób. Próbuję przejść przez to, że nie ma znaczenia, w jaki sposób liczby są implementowane w Pythonie. Nie ważne. Liczy się tylko to, że zachowują się jak liczby.
Andrej Bauer,
3
Wreszcie ogólne rozwiązanie dla dowolnej bazy i nieograniczone do konkretnych przypadków użycia, baz mniejszych niż 36 lub przypadków, w których można wymyślić wystarczającą liczbę unikalnych symboli.
J.Money
21

Myślę, że najlepszym sposobem na zrozumienie tego jest dyskusja z kosmitą (przynajmniej analogicznie).

Definicja jest liczbą w bazie b, coxb oznacza, że jest ciągiem cyfr < bx<b .

Przykłady Ciąg cyfr 10010011011 jest liczbą w podstawie 2, ciąg 68416841531 jest liczbą w podstawie 10, BADCAFE jest liczbą w podstawie 16.

Załóżmy teraz Dorastałem na planecie QUUX gdzie każdy uczy się pracy w przez całe swoje życie, a ja cię poznać, który jest stosowany do podstawowego bqb . Więc pokaż mi numer i co mam zrobić? Potrzebuję sposobu, aby to zinterpretować:

Definicja Mogę zinterpretować liczbę w podstawie (Uwaga: b jest liczbą w podstawie q ) według następującego wzorubbq

[[ϵ]]=0[[s¯re]]=[[s¯]]×b+re

gdzie oznacza ciąg pusty, a ˉ s d oznacza ciąg kończący się w cyfrowym d . Zobacz mój dowód, że dodatek stanowi wprowadzenie do tej notacji.ϵs¯rere

Co się tu stało? Podałeś mi liczbę w podstawie a ja zinterpretowałem ją w podstawie q bez jakiejkolwiek dziwnej filozofii na temat tego, jakie naprawdę są liczby.bq

Klucz Kluczem do tego jest to, że i + I są funkcjami, które działają na bazowychliczbach q . Są to proste algorytmy zdefiniowane rekurencyjnie na podstawie q liczb (ciągów cyfr).×+qq


Może się to wydawać nieco abstrakcyjne, ponieważ przez cały czas używałem zmiennych, a nie liczb rzeczywistych. Załóżmy więc, że jesteś stworzeniem podstawowym 13 (używając symboli ), a ja jestem przyzwyczajony do bazy 7 (co jest znacznie bardziej rozsądne), używając symboli α β γ δ ρ ζ ξ .0123456789XYZαβγδρζξ

Widziałem twój alfabet i zestawiłem go tak:

0α1β2)γ3)δ4ρ5ζ6ξ7βα8ββ9βγXβδYβρZβζ

βξ

60Z8

[[60Z8]]=ξ(βξ)3)+α(βξ)2)+βζ(βξ)+ββ

Zacznę od pomnożenia βζ×βξ

Tabela mnożenia Quuxa

×βγδρζξββγδρζξγγρξβββδβζδδξβγβζγβγρρρβββζγγγξδδζζβδγβγξδρργξξβζγρδδργζββαβαγαδαραζαξα

βζ×βξ

βζ×βξξγρβζδβγγ

więc mam tak daleko

[[60Z8]]=ξ(βξ)3)+α(βξ)2)+βζ(βξ)+ββ=ξ(βξ)3)+α(βξ)2)+δβγ+ββ

Teraz muszę wykonać dodawanie za pomocą algorytmu, o którym była mowa wcześniej:

δβγββδγδ

więc

[[60Z8]]=ξ(βξ)3)+α(βξ)2)+βζ(βξ)+ββ=ξ(βξ)3)+α(βξ)2)+δβγ+ββ=ξ(βξ)3)+α(βξ)2)+δγδ

[[60Z8]]=ζδξγρ.

qbq

Dyskretna jaszczurka
źródło
1
Cóż, to było sporo zawijasów. Jak sprawić, by komputer to zrobił?
Griffin,
1
@ Griffin, myślę, że zadajesz to (dziwne) pytanie przedwcześnie. Wybierasz język programowania i wpisujesz algorytm dodawania i mnożenia bazowych liczb q (przedstawionych jako listy cyfr), a następnie definiujesz funkcję interpretacji cyfr b podstawowych na liczby q podstawowe i interpretacji liczb b podstawowych na liczby q bazowe. Wyjaśniłem to wszystko.
Rzecz w tym, że znam koncepcję, którą próbujesz przedstawić. Mój problem polega na tym, że mój komputer nie może używać twoich zawijasów.
Griffin,
Wiem, co wyjaśniłeś, ale wdrożenie tego w praktyce jest znacznie trudniejsze. Widzisz, zdefiniowanie tych cyfr nie jest tak łatwe.
Griffin,
1
A także dlaczego upuściłeś cyfrę alfa na najbardziej znaczącej pozycji? Ponieważ 6 = & xi ;, Czy 7 = & alpha; & alpha ;?
Giovanni Botta
9

To tylko refaktoryzacja (Python 3) Andreja kodu . W kodzie Andreja liczby są reprezentowane przez listę cyfr (skalary), natomiast w poniższym kodzie numery są reprezentowane przez listę symboli pobranych z niestandardowego ciągu :

def v2r(n, base): # value to representation
    """Convert a positive number to its digit representation in a custom base."""
    b = len(base)
    digits = ''
    while n > 0:
        digits = base[n % b] + digits
        n  = n // b
    return digits

def r2v(digits, base): # representation to value
    """Compute the number represented by string 'digits' in a custom base."""
    b = len(base)
    n = 0
    for d in digits:
        n = b * n + base[:b].index(d)
    return n

def b2b(digits, base1, base2):
    """Convert the digits representation of a number from base1 to base2."""
    return v2r(r2v(digits, base1), base2)

Aby wykonać konwersję wartości do reprezentacji w bazie niestandardowej:

>>> v2r(64,'01')
'1000000'
>>> v2r(64,'XY')
'YXXXXXX'
>>> v2r(12340,'ZABCDEFGHI') # decimal base with custom symbols
'ABCDZ'

Aby wykonać konwersję z reprezentacji (w niestandardowej bazie) na wartość:

>>> r2v('100','01')
4
>>> r2v('100','0123456789') # standard decimal base
100
>>> r2v('100','01_whatevr') # decimal base with custom symbols
100
>>> r2v('100','0123456789ABCDEF') # standard hexadecimal base
256
>>> r2v('100','01_whatevr-jklmn') # hexadecimal base with custom symbols
256

Aby wykonać konwersję bazy z jednej bazy klienta do innej:

>>> b2b('1120','012','01')
'101010'
>>> b2b('100','01','0123456789')
'4'
>>> b2b('100','0123456789ABCDEF','01')
'100000000'
mmj
źródło
1
Witamy na stronie i dziękuję za Twój wkład. Jednak tworzenie dobrze zoptymalizowanego kodu źródłowego nie jest tym, na czym naprawdę polega ta strona. Kod Andreja wyjaśnia pojęcia, co jest potrzebne do jego odpowiedzi, ale poprawa kodu poza tym jest kwestią programowania, a nie informatyki .
David Richerby,
1
@DavidRicherby Częściowo się zgadzam, ale ten wkład był zbyt długi, aby mógł zostać skomentowany, a jego najlepszym miejscem jest gdzieś w pobliżu odpowiedzi Andreja, dlatego opublikowałem go tutaj. W każdym razie, jeśli uważasz, że lepiej, żebym mógł przekształcić go w komentarz z linkiem do kodu, ale czy nie byłby to nadmiar puryzmu?
mmj
1

Podstawową operacją konwersji podstawowej jest toDigits()operacja odpowiedzi @AndrejBauer. Jednak aby to zrobić, nie ma potrzeby tworzenia liczby w wewnętrznej reprezentacji liczb, co jest w zasadzie konwersją zi do reprezentacji 2 bazowej. Możesz wykonać niezbędne operacje w oryginalnej reprezentacji bazowej.

Pierwszym krokiem jest wykonanie powtarzalnej operacji dzielenia modulo

def convertBase(n,original_base,destination_base):
    digits = []    
    while not is_zero(n):
        digits.insert(0,modulo_div(n,original_base,destination_base))
    return digits

Ponieważ wewnętrzną reprezentacją są cyfry, należy wykonać specjalną funkcję do testowania zera

def is_zero(n):
    for d in n:
        if d != 0:
            return False
    return True

W końcu należy wykonać operację modulo_div, która jest tak naprawdę standardowym podziałem według bazy docelowej, jak uczyliśmy się w szkole.

def modulo_div(n,original_base,destination_base):
    carry = 0
    for i in range(len(n)):
        d = n[i]
        d+=original_base*carry 
        carry = d%destination_base 
        d=(d//destination_base)
        n[i] = d
        #print(i,d,carry)
    return carry

tylko test sprawdzający, czy kod jest poprawny:

print(convertBase([1,1,2,0], 3, 2))
#[1, 0, 1, 0, 1, 0]

print(convertBase([1, 0, 1, 0, 1, 0], 2, 3))
#[1, 1, 2, 0]
Xavier Combelle
źródło
Dziękujemy za opublikowanie, ale pamiętaj, że nie jesteśmy witryną kodującą, więc duży blok kodu nie jest odpowiedni jako odpowiedź tutaj. Zwłaszcza, gdy pytanie wyraźnie mówi: „Nie potrzebuję kodu, potrzebuję tylko podstawowej matematyki”.
David Richerby
@DavidRicherby Próbowałem dodać tekst.
Xavier Combelle
Dzięki. I widzę, że na tej stronie jest mnóstwo kodu, pomimo tego, co powiedziałem!
David Richerby
0

Znam prosty sposób na konwersję podstawową, która nie wymaga programu komputerowego. Jest to poprzez zdefiniowanie sposobu konwersji z dowolnej bazy na bazę 2 i odwrotnie, a następnie pokrycie z jednej bazy na inną bazę poprzez najpierw konwersję z pierwszej bazy na bazę 2, a następnie konwersję z bazy 2 na drugą bazę. 2 jest bardzo łatwy do pomnożenia lub podzielenia przez dowolną bazę.

Aby przekonwertować z dowolnej bazy na bazę 2, wystarczy, że rozpoznasz to dla dowolnej liczby, jeśli weźmiesz jej notację podstawy 2 i zaczniesz od 0, a następnie dla każdej cyfry w kolejności od lewej do prawej podwójnie, jeśli cyfra jest równa zero i podwójnie niż dodaj 1, jeśli ta cyfra to 1, dostaniesz się do tej liczby. Biorąc pod uwagę tę liczbę w dowolnej bazie, możesz podzielić przez 2 w tej bazie, aby otrzymać iloraz i resztę. Jeśli reszta to 1, ostatnia cyfra binarna to 1, a jeśli reszta to 0, ostatnia cyfra binarna to 0. Ponownie podziel przez 2. Jeśli reszta to 1, druga ostatnia cyfra to 1, a jeśli reszta to 0, druga ostatnia cyfra to 0 i tak dalej, aż otrzymasz iloraz 0.

Aby przekonwertować z bazy 2 na dowolną bazę, wszystko co musisz zrobić, to w tej bazie rozpocząć od 0, a następnie dla każdej cyfry binarnej przechodzącej od lewej do prawej, podwój w tej bazie, jeśli ta cyfra to 0, a następnie dodaj 1 w tej podstawa, jeśli cyfra to 1.

Tymotka
źródło
2 is so easy to multiply or divide by in any base.Nie widzę tego w przypadku baz nieparzystych, które są więcej niż jedną z dowolnej potęgi dwóch (na początek 11 i 13).
Greybeard
0

Możesz dokonać konwersji z bazy n na bazę 10 bez jakiejkolwiek konwersji na jakąś bazę pośrednią.

Aby na przykład przekonwertować bazę n na bazę 9, weź algorytm konwersji na bazę 10 i zamień „10” na „9”. To samo dla każdej innej bazy.

gnasher729
źródło