NOVINKA! E-learningové kurzy umělé inteligence. Nyní AI za nejlepší ceny. Zjisti více:
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!
Avatar
Kami-sama
Člen
Avatar
Kami-sama:28.12.2017 20:07

Existuje nějaký obecný algoritmus pro převádění mezi číselnými soustavami? Třeba z 25 soustavy do 9?
Měli jsme za dů to naprogramovat, soustavy 2 - 36. Dělala jsem to tak, že jsem to číslo dala nejdřív do desítkový a pak do tý zvolený, ale bylo to špatně v tom smyslu, že to asi pro nějaký velký vstup trvalo moc dlouho. Ale nikde jsem to nenašla obecně, nebo našla ale v jinom jazyku a tomu nerozumím. Děkuji za rady.

 
Odpovědět
28.12.2017 20:07
Avatar
Martin Dráb
Tvůrce
Avatar
Odpovídá na Kami-sama
Martin Dráb:28.12.2017 20:56

Jak moc velké jsou vstupy? Vejdou se do datového typu Longint? Pokud ano, lze při konverzi ze soustavy a do soustavy b postupovat podobně, jak píšeš:

  1. zkonvertovat z a do proměnné číselného typu (třeba ten Longint),
  2. zkonvertovat hodnotu této proměnné do b.

Jedná se vlastně o převod do dvojkové soustavy, ale dosti asistovaný samotným procesorem a tím, jak se ukládají data v paměti. Zároveň lze pro oba kroky využít matematické operace podporované procesorem.

Pokud jsou ty vstupy tak velké, že se nevejdou do typu Longint, můžeš provést přímo krok 2), ale musíš si implementovat vlastní matematickou operaci dělení (a modulo) na řetězcích reprezentující ta čísla v soustavách a a b. Což je těžší a také pomalejší.

Nahoru Odpovědět
28.12.2017 20:56
2 + 2 = 5 for extremely large values of 2
Avatar
Kami-sama
Člen
Avatar
Kami-sama:28.12.2017 21:20

Ptala jsem se, a prý by se měli do longint vejít, proto jsem to dělala pomocí tý desítkový.
Tady mám ty dvě funkce. Ty navrhuješ to převádět do dvojkový a z ní pak do tý b soustavy?

FUNCTION PrevedDoDesit­kove(cislo: string; var soustavaZ: byte): longint;
var i : integer; velkecislo: longint;
begin
velkecislo:= 0;
for i:= 1 to length(cislo) do begin
if (ord(cislo[i]) >= ord('a')) and (ord(cislo[i]) <= ord('z')) then
velkecislo:= velkecislo * soustavaZ + ord(cislo[i]) - ord('a') + 10 {prevede pismeno na cislo a ulozi do pole}
else velkecislo:= velkecislo * soustavaZ + ord(cislo[i]) - ord('0');
end;
PrevedDoDesitkove:= velkecislo;
end;

FUNCTION PrevedZDesitko­ve(cislo: longint; var soustava: byte): string;
var i, j: integer; S: string; A: array[1..1000] of integer;
begin
i:= 0; S:= '';
while cislo <> 0 do begin
i:= i + 1;
A[i]:= cislo mod soustava;
cislo:= cislo div soustava;
end;
for j:= i downto 1 do begin
if A[j] >= 10 then S[j]:= chr(A[j] - soustava + ord('a')) {prevede cislo vetsi jak 9 na pismeno}
else S:= S + chr(A[j] + ord('0'));
end;
PrevedZDesitkove:= S;
end;

 
Nahoru Odpovědět
28.12.2017 21:20
Avatar
Martin Dráb
Tvůrce
Avatar
Odpovídá na Kami-sama
Martin Dráb:28.12.2017 22:37

Z kódu vidím, že to děláš přesně v těch dvou krocích, jak jsem navrhoval. Funkce PrevedDoDesitkove ti to číslo převede ze zadané soustavy do proměnné typu longint, která je interně reprezentována ve dvojkové soustavě (ne v desítkové, navíc každý jeden bit reprezentuje jednu cifru dvojkového zápisu).

Co se týče PrevedZDesitkove, ta převádí z toho lognitu do cílové soustavy. Myslím, že jeden řádek by sis měla upravit na (zjevně jsi se tam překlepla se jménem proměnné)

if A[j] >= 10 then S[j]:= chr(A[j] - 10 + ord('a')) {prevede cislo vetsi jak 9 na pismeno}

Obecně bych ty funkce nazval PrevedNaLongint a PrevedZLongintu.

Myslím, že funkce PrevedZDesitkove ti jako výsledek vrátí zápis čísla v cílové soustavě, ale v opačném pořadí (tzn. nejméně významná cifra (jednotky) je jako první).

Navíc si nejsem jistý, zda-li lze zacházet s řetězcem tak, jak jej tam používáš (tzn. nastavit jej na prázdný řetězec a pak přiřazovat do jeho indexů... ale může to fungovat dobře, nevím). Po vyplnění pole A bych zavolal

SetLength(s, i);

protože víme, že výsledná podoba čísla bude mít právě i cifer. Pokud daná verze jazyka tuto funkci podporuje (to už si bohužel nepamatuju).

Nahoru Odpovědět
28.12.2017 22:37
2 + 2 = 5 for extremely large values of 2
Avatar
Kami-sama
Člen
Avatar
Kami-sama:28.12.2017 22:50

Dík. Měla by to vracet ve správném pořadí, protože to pole procházím odzadu.
A tu proceduru SetLength neznám, je možný že ve free pascalu funguje, ale já jsem začátečník v tomhle takže znám spíš jen to co jsme probírali a ne moc věcí navíc.
Já už jsem teda vyřešila to že to v tom programu kam to dáváme kontrolovat trvalo moc dlouho, ale mám tam zase chyby v odpovědi.
Zbytek toho programu mám takhle, kdyby se ještě kouknul a dal třeba radu jak to zlepšit. Děkuji.

BEGIN
assign(Vstup, JmenoVstupu); assign(Vystup, JmenoVystupu); reset(Vstup); rewrite(Vystup); pocet:= 0; textcislo:= '';
read(Vstup, znak);
while znak <> '>' do begin
textcislo:= textcislo + znak;
read(Vstup, znak);
end;
Val(textcislo, soustavaZ, kodchyby); {soustavaZ je soustava ze ktere se prevadi}
textcislo:= '';
read(Vstup, znak);
textcislo:= textcislo + znak;
read(Vstup, znak);
if (ord(znak) >= ord('2')) and (ord(znak) <= ord('9')) then textcislo:= textcislo + znak;
Val(textcislo, soustavaDO, kodchyby); {soustavaDO je soustava do ktere se prevadi}
readln(Vstup);
while not(eof(Vstup)) do begin
readln(Vstup, cislo);
pocet:= pocet + 1;
CislaNaPrevod[po­cet]:= cislo;
end;
for i:= 1 to pocet do begin
desitkovecislo:= PrevedDoDesit­kove(CislaNaPre­vod[i], soustavaZ); {prvni cislo ze vstupu prevedu ze soustavy ve ktere je do desitkove}
prevedenecislo:= PrevedZDesitko­ve(desitkovecis­lo, soustavaDO);
writeln(Vystup, prevedenecislo);
end;
close(Vystup); close(Vstup);
END.

 
Nahoru Odpovědět
28.12.2017 22:50
Avatar
Martin Dráb
Tvůrce
Avatar
Odpovídá na Kami-sama
Martin Dráb:28.12.2017 23:18

Měla by to vracet ve správném pořadí, protože to pole procházím odzadu.

Pravda.

Zbytek toho programu mám takhle, kdyby se ještě kouknul a dal třeba radu jak to zlepšit. Děkuji.

Jeslti to chápu správně, tak formát vstupního souboru je takový, že na prvním řádku je zadána vstupní a výstupní soustava oddělená znakem >. Na dalších řádkách následují čísla pro převedení (každé na jednom řádku).

Zkusil bych načítat i ten první řádek celý najednou. Zároveň nemusíš načíst všechna čísla a až potom je převádět, můžeš vždy načíst číslo, převést jej, vypsat jej na výstup, načíst další... dokud vstup neskončí. Asi nějak takto:

var
  i : integer;
  radek : string;
. . .
begin
assign(Vstup, JmenoVstupu);
assign(Vystup, JmenoVystupu);
reset(Vstup); rewrite(Vystup);
readln(vstup, radek);
textCislo := '';
i := 1;
Whle radek[i] <> '>' Do
  begin
  textCislo := textCislo + radek[i];
  i := i + 1;
  end;

val(textCislo, soustavaZ, kodChyby);
i := i + 1;
textCislo := '';
While i < Length(radek) Do
  begin
  textCislo := textCislo + radek[i];
  i := i + 1;
  end;

val(textCislo, soustavaDO, kodChyby);
While Not EOF(vstup) Do
  begin
  readln(vstup, textCislo);
  desitkoveCislo := prevedDoDesitkove(textCislo, soustavaZ);
  prevedeneCislo := prevedZDesitkove(desitkoveCislo, soustavaDO);
  writeln(vystup, prevedeneCislo);
  end;

close(vstup);
close(vystup);
end.

Možná to nebude přímo fungovat, ale mělo by to být dost blízko. Zároveň tam řeším problém s konverzí cílové soustavy na číslo (kde tvůj původní kód bude mít problém (podle mě), pokud je třeba cílová soustava 11).

Nahoru Odpovědět
28.12.2017 23:18
2 + 2 = 5 for extremely large values of 2
Avatar
Kami-sama
Člen
Avatar
Odpovídá na Martin Dráb
Kami-sama:29.12.2017 10:37

Chápeš to dobře, děkuji.

Možná to nebude přímo fungovat, ale mělo by to být dost blízko. Zároveň tam řeším problém s konverzí cílové soustavy na číslo (kde tvůj původní kód bude mít problém (podle mě), pokud je třeba cílová soustava 11).

Jaký problém přesně? Nevidím to v tom.

 
Nahoru Odpovědět
29.12.2017 10:37
Avatar
Martin Dráb
Tvůrce
Avatar
Odpovídá na Kami-sama
Martin Dráb:29.12.2017 10:51

Konkrétně jde o kus kódu načítající cílovou soustavu

textcislo:= '';
read(Vstup, znak);
textcislo:= textcislo + znak;
read(Vstup, znak);
if (ord(znak) >= ord('2')) and (ord(znak) <= ord('9')) then textcislo:= textcislo + znak;
Val(textcislo, soustavaDO, kodchyby);

Jednak tam předpokládáš, že cílová soustava bude mít dvě cifry (což třeba devítková nemá). Pak v případě, že druhá cifra je 0 nebo 1, ji nepřidáváš do textCislo, takže se ti do soustavaDO uloží (podle mě) špatné číslo. Tam bys spíš měla kontrolovat, že soustavaDO po volání funkce val je ve správném rozsahu, tedy >= 1 a <= 36 (i jedničková soustava existuje, pokud zadání neříká jinak).

Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
29.12.2017 10:51
2 + 2 = 5 for extremely large values of 2
Avatar
Kami-sama
Člen
Avatar
Odpovídá na Martin Dráb
Kami-sama:29.12.2017 11:34

Jo už to chápu, díky moc. :-)

 
Nahoru Odpovědět
29.12.2017 11:34
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 9 zpráv z 9.