Zaawansowana konwersja dec2bin

0

Witajcie. Jestem w trakcie projektowania pewnego systemu przetwarzającego dane i będzie on bazował głównie na ogromnych liczbach. Owe liczby z pogranicza zakresu Cardinal będą konwertowane na binarny ciąg do zmiennej String no i będzie też konwersja w drugą stronę.

Pozwoliłem sobie ściągnąć gotowce z netu - funkcje do konwersji, następujące:

function dec2bin(d:cardinal):string;
begin
result:='';
if d<>0 then
while d<>0 do begin
result:=inttostr(d mod 2)+result;
d:=d div 2;
end else result:='0';
end;
function bin2dec(b:string):cardinal;
var i:integer;
begin
result:=0;
for i:=1 to length(b) do
if b[i]='1' then result:=result*2+1 else result:=result*2;
end;

Niestety nie działają one w sposób, jakiego oczekuję, a nie znam się na tyle na rodzajach zmiennych, aby sobie z tym poradzić. Załóżmy, że mam liczbę binarną 11010101010101010010101100101 i chciałbym ją zapisać jako liczbę dziesiętną, ale naturalną. Niestety jedyna z przodu powoduje, że funkcją podaną powyżej dostaję liczbę ujemną, co niszczy mi algorytm, który spodziewa się wyłącznie cyfr lub znaku CF/LF.

W drugą stronę - liczby wczytywane są z pliku, którego zawartość to różne liczby całkowite (a chciałbym naturalne) oddzielone enterami, np:

1853124467
824193080
-1878589436
67108864
3158320
672
-1610350591
16777216
131077

Potrzebuję, żeby ktoś ogarnięty w temacie wytłumaczył mi jak skonwertować dowolną liczbę naturalną (Cardinal) na binarną w taki sposób, aby po konwersji w drugą stronę dostać całkowitą dodatnią, a nie całkowitą ujemną liczbę :( Cały dzień z tym walczę, szlag mnie trafia, to pewnie jest proste, ale ja nie jestem programistą i pewnych rzeczy nie kumam (nawet nie wiem co to są klasy :)). Pozdrawiam

1
derlee napisał(a)

Załóżmy, że mam liczbę binarną 11010101010101010010101100101 i chciałbym ją zapisać jako liczbę dziesiętną, ale naturalną. Niestety jedyna z przodu powoduje, że funkcją podaną powyżej dostaję liczbę ujemną

11010101010101010010101100101 zwraca 447391077. tam nie ma minusa. malo tego, ta funkcja nigdy nie zwroci ujemnej liczby.

0

Oki, to trochę inaczej:

Program czyta z dowolnego pliku 256 kolejnych znaków (Char), przypisując do tablicy

c: array[1..256] of Char

owe znaki.
Każdy z tych znaków zamieniany jest na liczbę (funkcja

ord(c[i])

) a więc dostajemy liczbę z zakresu 0..255, która jest konwertowana na format binarny (do zmiennej String) z dopełnieniem do ośmiu znaków (np. jeśli znak #7 zamieni się na 111 to zmienna String uzupełnia się do 00000111). Tak jest ze wszystkimi 256 znakami. Wszystkie skonwertowane na binarne Stringi łączone są w jeden, więc jeżeli w pliku znajdowały się znaki #7 #7 #7 #7 #7 #7 ... #7 to otrzymujemy jednego stringa o wartości 000001110000011100000111000001110000011100000111 ... 00000111. Jest to liczba (tekst...) w systemie binarnym w zmiennej String o długości 8256. Taką binarną liczbę chcę zamienić na liczbę taką normalną liczbę (może Extended zamiast Cardinal?) i potem chcę mieć możliwość odtworzenia ciągu zer i jedynek za pomocą odwrotnej funkcji, czyli z ogromnej liczby chcę uzyskać 8256 długości ciąg zer i jedynek, który podzielę sobie na bloki po 8 bitów i zamienięz powrotem na kody ASCII i odtworzę pierwotne znaki.

Z tym jest problem, bo pojawia się

EConvertError: '' is not avalid integer value

Aplikacja jest w Delphi 2007 w trybie konsolowym. Wklejam część kodującą z pliku do liczb oraz drugą z liczb do pliku, która się wywala:

Zamiana z pliku na liczby do innego pliku:

var
  file_input: file of char;
  file_output: text;
  file_input_name, file_output_name: string;
  c: array[1..256] of char;
  bufor: integer;
  i: integer;
  b, fs, fw: longint;
  bin: string;
  bin2: string;
  line_str: string;
  line_int: longint;

...

while not eof(file_input) do
   begin
   read(file_input, c[bufor]);
   bin:= dec2bin(ord(c[bufor]));
   bin2:='00000000';

   for i := 1 to 8 do
    if bin[i]='1' then bin2[i+8-length(bin)]:='1';

   line_str:=line_str+bin2;

   if bufor=bufor_dlugosc then
      begin
      line_int:=bin2dec(line_str);
      str(line_int, line_str);
      write(file_output, line_str);
      writeln(file_output, '');
      fw:=fw+length(line_str)+2;
      line_str:='';
      bufor:=0;
      end;
   end; // eof(file_input);

   if bufor>0 then
   begin
     line_int:=bin2dec(line_str);
      str(line_int, line_str);
      write(file_output, line_str);
      writeln(file_output, '');
      fw:=fw+length(line_str)+2;
      line_str:='';
      bufor:=0;
   end;

I to mi zapisuje fajnie plik tekstowy, np:
4802858
16777216
7208960
10241
16908317
352321536
131072
11521
16777217
1869901683
1853124467
824193080
-1878589436
67108864
3158320
672
-1610350591
16777216
i tak dalej.

W drugą stronę nie ma rewelacji, bo plik odczytuje się stringami, z tą różnicą, że czytany plik jest typu textfile a nie file of char. Każda linijka zczytywana jest do Stringa, który przez Val jest zamieniana na zmienna Cardinal. Potem oczywiście Cardinal dziesiątkowy na Stringa binarnego za pomocą podanej na początku funkcji dec2bin. I jest Exception. W kodzie zaszył się automatycznie taki cudak:

except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);

Całą aplikacja działa oczywiście w sekcji try.
Pomożecie?

0
 
   read(file_input, c[bufor]);
   bin:= dec2bin(ord(c[bufor]));

a po co czytasz wszystko do tablicy C skoro i tak ciągle ustawiasz bufor na 0.... . Albo może i zwiększasz to ale nie mogłeś pokazać tego..

 
   for i := 1 to 8 do
    if bin[i]='1' then bin2[i+8-length(bin)]:='1';

Czemu to odwracasz, na dodatek tak dziwnie?

   if bufor=bufor_dlugosc then
      begin
      line_int:=bin2dec(line_str);
      str(line_int, line_str);
      write(file_output, line_str);
      writeln(file_output, '');
      fw:=fw+length(line_str)+2;
      line_str:='';
      bufor:=0;
      end;

Ciekaw jestem czy to się kiedykolwiek wykona. I ciekaw jestem do czego służy zmienna fw, którą tak ładnie nazwałeś że wszyscy rozumiemy.

Dwie rzeczy o których musisz poczytać (google it):
1.Debugger - pomoże ci znaleźć błąd
2.Przekroczenie zakresu - czyli co się dzieje jak za dużo bitów chcesz wepchnąć do jednej liczby.

0

trzeba bylo tak od razu... bo pojawia sie pytanie: po jaka cholere tak? nie mozesz tego inaczej rozwiazac?
chyba najwiekszym typem w delphi, jesli chodzi o liczby calkowite jest int64 - sklada sie z 8bajtów czyli 64 bitów.
a Ty probujesz utworzyc liczbe, ktora sklada sie z... 256*8 = 2048bitow....
nie da sie, nie bez jakichś dodatkowych klas (chociaz i tak nie wiesz co to jest...)
napisz do czego Ci takie konwertowanie jest potrzebne.

1 użytkowników online, w tym zalogowanych: 0, gości: 1