Diskuze: Převod mezi soustavami - Pascal
Člen
Zobrazeno 9 zpráv z 9.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
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š:
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ší.
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 PrevedDoDesitkove(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 PrevedZDesitkove(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;
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).
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[pocet]:= cislo;
end;
for i:= 1 to pocet do begin
desitkovecislo:= PrevedDoDesitkove(CislaNaPrevod[i], soustavaZ); {prvni
cislo ze vstupu prevedu ze soustavy ve ktere je do desitkove}
prevedenecislo:= PrevedZDesitkove(desitkovecislo, soustavaDO);
writeln(Vystup, prevedenecislo);
end;
close(Vystup); close(Vstup);
END.
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).
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.
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).
Zobrazeno 9 zpráv z 9.