Konwersja z systemu dziesiętnego na inny o dowolnej podstawie.

netvalker

Do sekcji Uses dodajemy StrUtils
Następnie tworzymy tablicę zawierającą szesnaście znaków:

Const
     SignBase : array [0..15] Of String[1] =
        (('0'),('1'),('2'),('3'),('4'),
         ('5'),('6'),('7'),('8'),('9'),
         ('a'),('b'),('c'),('d'),('e'),
         ('f'));

Teraz tworzymy funkcję, do której w postaci parametrów wyślemy liczbę, która będzie poddana konwersji oraz podstawę systemu liczbowego, na który ową liczbę będziemy konwertować. A funkcja zwracać będzie wartość typu String;

Function  DecToAny(Decimal : Integer; Base : byte) : String;

W tworzeniu funkcji skorzystamy z pętli While oraz poleceń div i mod.

    While Decimal <> 0 do \\ wykonuj pętlę dopóki wartość decimal nie osiągnie zera
      Begin
       Result := Result + SignBase[(Decimal Mod Base)];\\ do wyniku funkcji dodajemy znak z utworzonej tablicy za pomocą obliczonej wartości operatora Mod
       Decimal := Decimal div Base; \\ wykonujemy dzielenie obniżając wartość decimal
      End;

Dodajemy jeszcze jedną pętlę While aby wynik z obliczeń dla systemu Dwójkowego i Sześciennego był poprawny.

While (((Length(Result) < 4) And ((Base = 2))
            Or
            ((Length(Result) < 2) And ((Base = 16)))))
            do
      Result := Result + '0';

Na koniec odwracamy String aby był właściwie wyświetlany.

Result := StrUtils.ReverseString(Result);  
End;

Cała funkcja wygląda tak:

Function DecToAny(Decimal : Integer; Base : byte) : String;
Begin
     While Decimal <> 0 do
       Begin
        Result := Result + SignBase[(Decimal Mod Base)];
        Decimal := Decimal div Base;                     
      End;
     While (((Length(Result) < 4) And ((Base = 2))
               Or
               ((Length(Result) < 2) And ((Base = 16)))))
               do 
               Result := Result + '0'; 
     Result := StrUtils.ReverseString(Result); 
End;

Przykład użycia tej funkcji znajduje się w programiku konwersator :
http://4programmers.net/news.php?id=1862

5 komentarzy

Faaaaaaaajnie.
:):(:]:[:-/

Nie wiem jak to działa, ale dzięki, przyda się do pracy. Jedyny mankament jest chyba z liczbami ujemnymi, ale postaram się coś na to zaradzić, może na podstawie tego dopisze drugą funkcję.

Nie czepiam sie specjalnie. Tylko, że no po prostu... Może potraktuj to jako uzupełnienie, dla tych początkujcych, którzy sami sobie nie poradzą z poprawkami.

[quote]Flabra :
result:=signbase[i mod base]+result; [/quote]
Fakt nie pomyślałem - mój błąd.
To jest tylko przykład i nikt nie musi się go kurczowo trzymać!!

function l2a(i:cardinal;base,minlen:byte):string;
const signbase:array[0..35]of char='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
begin
result:='';
repeat
result:=signbase[i mod base]+result;// Nie bój się, tu najpierw jest zapamiętanie (stos), potem przypisanie.
i:=i div base;
until i=0;
while(length(result)<minlen)do result:=#48+result;
end;

Bez odwracania i zawsze jest przynajmniej jeden znak. Poza tym, przy cyfrach 0..f nie wyskoczysz poza system 16owy. Tablica signbase... można ją zadeklarować, tak by zajmowała mniej miejsca (2x mniej). Przy przeliczaniu lepiej zapomnij o minusie (cardinal; integer($ffffffff)=-1 i jak zakodujesz -1?). Następne, liczby w pamięci nie są trzymane w systemie 10 (dectoany- nazwy to juz się czepiam, ale formalnie) jeśli już to 256owym (bajt), albo binarnym (bit), a w każdym razie jest to system 2^n (n=1,8,16,32,64,...)- interpretacja zależy tylko od programisty. Po ente, było (?? nie chcę przekłamać, ale na forum na pewno).