Serwis Edukacyjny w I-LO w Tarnowie ![]() Materiały dla uczniów liceum |
Wyjście Spis treści Wstecz Dalej
Autor artykułu: mgr Jerzy Wałaszek |
©2023 mgr Jerzy Wałaszek
|
Z liczbami zmiennoprzecinkowymi (ang. floating point numbers) spotkaliście się już zapewne na zajęciach z fizyki. Otóż zapis dużych liczb (lub bardzo małych) w normalnej notacji pozycyjnej jest niewygodny, gdyż wymaga sporej ilości cyfr. Dlatego liczby takie zapisuje się w sposób następujący:
Zapis składa się z trzech liczb:
m - mantysy, u nas równej 3,25 p - podstawy systemu, u nas równej 10 c - cechy, u nas równej 33 |
Wartość liczby zmiennoprzecinkowej obliczamy zgodnie ze wzorem:
Wzór pozwala obliczyć wartość liczby zmiennoprzecinkowej zapisanej w dowolnym systemie pozycyjnym, a nie tylko dziesiętnym.
Przykład:
Obliczyć wartość zmiennoprzecinkowej liczby trójkowej 2,21 · 1021(3).
Najpierw obliczamy wartości poszczególnych składników liczby zmiennoprzecinkowej pamiętając, iż każdy z nich jest zapisany w systemie trójkowym:
Teraz wykorzystujemy podany wzór do wyznaczenia wartości dziesiętnej tej liczby:
Przykład:
Obliczyć wartość zmiennoprzecinkowej liczby szesnastkowej A,CB · 10D.
Zapis zmiennoprzecinkowy - skąd wzięła się nazwa tego sposobu zapisu liczb? Otóż położenie przecinka w mantysie nie jest ustalone i może się dowolnie zmieniać. Poniższe zapisy oznaczają tę samą liczbę:
Oczywiście zmiana położenia przecinka w mantysie wpływa na wartość cechy liczby. Reguła jest bardzo prosta i obowiązuje we wszystkich systemach pozycyjnych (dlaczego?):
Przesunięcie przecinka o 1 pozycję w lewo wymaga
zwiększenia cechy o 1. |
Postaraj się uzasadnić te reguły dla dowolnego systemu pozycyjnego.
Ponieważ liczbę zmiennoprzecinkową można zapisywać w różny sposób, przyjęto tzw. postać znormalizowaną.
Umówmy się, iż znormalizowana liczba zmiennoprzecinkowa to taka, w której mantysa spełnia nierówność:
|
Według tej definicji z podanych na początku rozdziału zapisów zmiennoprzecinkowych postacią znormalizowaną jest jedynie zapis 3,25 · 1022. Normalizacja jest rzeczą umowną i istnieją również alternatywne definicje
Jeśli dokładnie przeczytaliście ze zrozumieniem poprzednie rozdziały naszego opracowania, to zadanie przeliczania liczb z systemu dziesiętnego na zapis zmiennoprzecinkowy w systemie o dowolnej podstawie jest dziecinnie łatwe. Jeśli nie, to proponuję to zrobić.
Algorytm przeliczania liczby dziesiętnej na liczbę zmiennoprzecinkową w innym systemie pozycyjnym |
---|
|
Przykład:
Dla przykładu zapiszmy liczbę dziesiętną 1275,125 jako zmiennoprzecinkową liczbę w systemie czwórkowym.
Najpierw przeliczamy liczbę 1275,125 na system czwórkowy. Robimy to osobno dla części całkowitej i ułamkowej:
1275 div 4 = | 318 | i reszta 3 |
318 div 4 = | 79 | i reszta 2 |
79 div 4 = | 19 | i reszta 3 |
19 div 4 = | 4 | i reszta 3 |
4 div 4 = | 1 | i reszta 0 |
1 div 4 = | 0 | i reszta 1, koniec |
1275(10) = 103323(4) |
Teraz przeliczamy na system czwórkowy część ułamkową liczby:
0,125 · 4 = | 0,5 | - cyfra 0 |
0,5 · 4 = | 2,0 | - cyfra 2 i kończymy, ponieważ część ułamkowa wynosi 0 |
0,125(10) = 0,02(4) |
Łączymy ze sobą oba wyniki i otrzymujemy postać czwórkową przeliczanej liczby dziesiętnej:
1275,125(10) = 103323,02(4) |
Liczbę tę zapisujemy z cechą równą 0, czyli
103323,02 · 100(4) |
Normalizujemy mantysę. W tym celu przecinek należy przesunąć o 5 pozycji w lewo, zatem cecha wzrośnie do wartości 5, co w systemie czwórkowym ma zapis 11(4) i ostatecznie:
1275,125(10) = 1,0332302 · 1011(4) |
Zadanie to można rozwiązać również w inny sposób. Mantysę i cechę docelowej liczby zmiennoprzecinkowej możemy wyznaczyć w systemie dziesiętnym, a następnie liczby te przeliczyć na system docelowy. Korzystamy tutaj z faktu, iż przesunięcie przecinka w systemie docelowym odpowiada pomnożeniu wartości liczby przez podstawę tego systemu (przesunięcie w prawo) lub podzieleniu jej przez podstawę (przesunięcie w lewo). Zatem:
1275,125 = 1275,125 · 40 1275,125 = 318,78125 · 41 1275,125 = 79,6953125 · 42 1275,125 = 19,923828125 · 43 1275,125 = 4,98095703125 · 44 1275,125 = 1,2452392578125 · 45 |
Teraz otrzymane liczby wystarczy zamienić na system czwórkowy i mamy gotową zmiennoprzecinkową postać znormalizowaną przeliczanej liczby.
m = 1,2452392578125 |
Część całkowita wynosi 1, obliczamy zatem część ułamkową mantysy:
0,2452392578125 · 4 = | 0,98095703125 | - cyfra 0 |
0,98095703125 · 4 = | 3,923828125 | - cyfra 3 |
0,923828125 · 4 = | 3,6953125 | - cyfra 3 |
0,6953125 · 4 = | 2,78125 | - cyfra 2 |
0,78125 · 4 = | 3,125 | - cyfra 3 |
0,125 · 4 = | 0,5 | - cyfra 0 |
0,5 · 4 = | 2,0 | - cyfra 2 i koniec, gdyż część ułamkowa wynosi zero |
m = 1,0332302(4) p = 4(10) = 10(4) c = 5(10) = 11(4) |
Zatem ostatecznie:
1275,125(10) = 1,0332302 · 1011(4) |
Program dokonuje przeliczenia liczby zmiennoprzecinkowej zapisanej w jednym systemie pozycyjnym na inny system pozycyjny. W programie wykorzystano prezentowane wcześniej algorytmy, dlatego nie opisujemy ich już tutaj.
Program odczytuje podstawę źródłową systemu pozycyjnego, w którym zapisana jest wejściowa liczba zmiennoprzecinkowa. Następnie odczytywana jest mantysa (jako liczba stałoprzecinkowa) oraz cecha (jako liczba całkowita). Zarówno mantysa jak i cecha muszą być zapisane w systemie pozycyjnym o podanej wcześniej podstawie. Na koniec podajemy podstawę systemu docelowego, a program oblicza wartość wprowadzonej liczby i przekształca ją na znormalizowany zapis zmiennoprzecinkowy w systemie docelowym.
Prezentowane algorytmy posiadają pewne ograniczenia. Czy potrafisz je znaleźć w tym programie? Zaproponuj sposoby ich uniknięcia.
C++// Program przeliczający liczby zmiennoprzecinkowe. //------------------------------------------------- // (C)2005 mgr Jerzy Wałaszek // I Liceum Ogólnokształcące // im. K. Brodzińskiego // w Tarnowie //------------------------------------------------- #include <cmath> #include <iostream> #include <string> using namespace std; // Funkcja sprawdza poprawność zapisu liczby // Wejście: // s - zapis liczby w postaci stałoprzecinkowej // p - podstawa systemu // intg - true = liczba musi być całkowita // Wyjście: // true, jeśli zapis jest prawidłowy //------------------------------------------------ bool Test(string s, unsigned p, bool intg) { int i,c; bool pc,prz; pc = prz = false; for(i = 0; i < s.length(); i++) switch(s[i]) { case '-' : if(pc || prz) return(false); else pc = true; case ' ' : break; case ',' : if(prz || intg) return(false); else prz = true; break; default : c = (int)(toupper(s[i])) - 48; if(c > 9) c -= 7; if(c >= p) return false; break; } return true; } // Funkcja oblicza wartość liczby // Wejście: // s - łańcuch znakowy z zapisem liczby // p - podstawa systemu liczbowego zapisu liczby // Wyjście: // wartość liczby zapisanej w s //------------------------------------------------ double Wartosc(string s, unsigned p) { unsigned c,i; long double Lc,Lu,w; int znak; bool u; Lc = Lu = 0; znak = 1; w = 1; u = false; for(i = 0; i < s.length(); i++) switch(s[i]) { case '-' : znak = -1; case ' ' : break; case ',' : u = true; break; default : c = (int)(toupper(s[i])) - 48; if(c > 9) c -= 7; if(u) { Lu = p * Lu + c; w *= p; } else Lc = p * Lc + c; break; } return znak * (Lc + Lu / w); } // Funkcja oblicza wartość potęgi // Wejście: // a - liczba podnoszona do potęgi // n - wartość wykładnika potęgowego // Wyjście: // a^n //------------------------------------ double Potega(int a, int n) { long double p; p = 1; while(n > 0) { p *= a; n--; } while(n < 0) { p /= a; n++; } return(p); } // Funkcja znajduje zapis stałoprzecinkowy podanej liczby // Wejście: // L - wartość liczby // p - podstawa systemu liczbowego zapisu liczby // Wyjście: // zapis liczby w systemie o podstawie p //------------------------------------------------------- string Przelicz(double L, unsigned p) { string sc,su; unsigned c; long double Lu,Lc; bool znak; znak = false; sc = su = ""; // Algorytm obsługuje liczby nieujemne. Jeśli więc wartość liczby // jest ujemna, to zapamiętujemy jej znak i zmieniamy ją na dodatnią if(L < 0) { L = -L; znak = true; } // Wyznaczamy część całkowitą Lc oraz część ułamkową Lu. // Część ułamkowa zostaje zaokrąglona do około 10 cyfr po // przecinku. Lc = floor(L); Lu = L - Lc; // Wyznaczamy zapis części całkowitej w sc do { c = (int)floor(Lc - floor(Lc / p) * p); if(c < 10) sc = (char)(c + 48) + sc; else sc = (char)(c + 55) + sc; Lc = floor(Lc / p); } while(Lc); // Jeśli część ułamkowa jest niezerowa, to wyznaczamy jej // zapis w su. Na końcu zapisu usuwamy zera nieznaczące if(Lu) { do { Lu = Lu * p; c = (int)floor(Lu); Lu = Lu - c; if(c < 10) su += (char)(c + 48); else su += (char)(c + 55); } while(Lu && su.length() < 10); while((su != "") && (su[su.length()-1] == '0')) su.erase(su.length()-1); su = "," + su; } // Jeśli konieczne, dodajemy znak liczby i całość łączymy // w jeden zapis. if(znak) sc = "-" + sc; return sc + su; } //********************** //*** PROGRAM GŁÓWNY *** //********************** main() { double m; int c; unsigned p1,p2; string s1,s2; char z[1]; cout << "Przeliczanie liczb zmiennoprzecinkowych\n" "---------------------------------------\n" "(C)2005 mgr Jerzy Walaszek I LO Tarnow\n\n" "Podstawa zrodlowa = "; cin >> p1; if((p1 > 1) && (p1 < 37)) { cout << "\nMantysa = "; cin >> s1; if(Test(s1,p1,false)) { cout << "Cecha = "; cin >> s2; if(Test(s2,p1,true)) { cout << "\nPodstawa docelowa = "; cin >> p2; if((p2 > 1) && (p2 < 37)) { // Obliczamy wartość liczby. Początkowo mantysa jest równa tej // wartości, a cecha jest równa 0. m = Wartosc(s1,p1) * Potega(p1,(int)Wartosc(s2,p1)); c = 0; // Normalizujemy mantysę do przedziału <1,p) if(m) { while(fabs(m) >= p2) { m /= p2; c++; }; while(fabs(m) < 1 ) { m *= p2; c--; } } cout << endl << s1 << "x10^" << s2 << "(" << p1 << ") = " << Przelicz(m,p2) << "x10^" << Przelicz(c,p2) << "(" << p2 << ")"; } else cout << "Nieprawidlowa podstawa docelowa"; } else cout << "Nieprawidlowa cecha"; } else cout << "Nieprawidlowa mantysa"; } else cout << "Nieprawidlowa podstawa zrodlowa"; cout << "\n\nNacisnij ENTER...\n"; cin.getline(z,1); cin.getline(z,1); } |
Pascal// Program przeliczający liczby zmiennoprzecinkowe. //------------------------------------------------- // (C)2005 mgr Jerzy Wałaszek // I Liceum Ogólnokształcące // im. K. Brodzińskiego // w Tarnowie //------------------------------------------------- program Systemy; {$APPTYPE CONSOLE} // Funkcja sprawdza poprawność zapisu liczby // Wejście: // s - zapis liczby w postaci stałoprzecinkowej // p - podstawa systemu // intg - true = liczba musi być całkowita // Wyjście: // true, jeśli zapis jest prawidłowy //------------------------------------------------ function Test(s : string; p : cardinal; intg : boolean) : boolean; var i,c : integer; pc,prz : boolean; begin Test := true; pc := false; prz := false; for i := 1 to length(s) do case s[i] of ' ' : continue; '-' : if pc or prz then begin Test := false; break; end else pc := true; ',' : if prz or intg then begin Test := false; break; end else prz := true; else begin c := ord(UpCase(s[i])) - 48; if c > 9 then dec(c,7); if c >= p then begin Test := false; break; end; end; end; end; // Funkcja oblicza wartość liczby // Wejście: // s - łańcuch znakowy z zapisem liczby // p - podstawa systemu liczbowego zapisu liczby // Wyjście: // wartość liczby zapisanej w s //------------------------------------------------ function Wartosc(s : string; p : cardinal) : real; var Lc,Lu,w : extended; c,i : cardinal; znak : integer; u : boolean; begin Lc := 0; Lu := 0; w := 1; u := false; znak := 1; for i := 1 to length(s) do case s[i] of '-' : znak := -1; ',' : u := true; else begin c := ord(UpCase(s[i])) - 48; if c > 9 then dec(c,7); if u then begin Lu := p * Lu + c; w := p * w; end else Lc := p * Lc + c; end; end; Wartosc := znak * (Lc + Lu / w); end; // Funkcja oblicza wartość potęgi // Wejście: // a - liczba podnoszona do potęgi // n - wartość wykładnika potęgowego // Wyjście: // a^n //------------------------------------ function Potega(a,n : integer) : real; var p : extended; begin p := 1; while n > 0 do begin p := p * a; dec(n); end; while n < 0 do begin p := p / a; inc(n); end; Potega := p; end; // Funkcja znajduje zapis stałoprzecinkowy podanej liczby // Wejście: // L - wartość liczby // p - podstawa systemu liczbowego zapisu liczby // Wyjście: // zapis liczby w systemie o podstawie p //------------------------------------------------------- function Przelicz(L : real; p : cardinal) : string; var sc,su : string; c : cardinal; Lc,Lu : extended; znak : boolean; begin znak := false; sc := ''; su := ''; // Algorytm obsługuje liczby nieujemne. Jeśli więc wartość liczby // jest ujemna, to zapamiętujemy jej znak i zmieniamy ją na dodatnią if L < 0 then begin L := -L; znak := true; end; // Wyznaczamy część całkowitą Lc oraz część ułamkową Lu. // Część ułamkowa zostaje zaokrąglona do około 10 cyfr po // przecinku. Lc := trunc(L); Lu := frac(L); // Wyznaczamy zapis części całkowitej w sc repeat c := trunc(Lc - trunc(Lc / p) * p); if c < 10 then sc := char(c + 48) + sc else sc := char(c + 55) + sc; Lc := trunc(Lc / p); until Lc = 0; // Jeśli część ułamkowa jest niezerowa, to wyznaczamy jej // zapis w su. Na końcu zapisu usuwamy zera nieznaczące if Lu > 0 then begin repeat Lu := Lu * p; c := trunc(Lu); Lu := Lu - c; if c < 10 then su := su + char(c + 48) else su := su + char(c + 55); until (Lu = 0) or (length(su) = 10); while (su <> '') and (su[length(su)] = '0') do Delete(su,length(su),1); su = "," + su end; // Jeśli konieczne, dodajemy znak liczby i całość łączymy // w jeden zapis. if znak then sc := '-' + sc; Przelicz := sc + su; end; //********************** //*** PROGRAM GŁÓWNY *** //********************** var m : real; c : integer; p1,p2 : cardinal; s1,s2 : string; begin writeln('Przeliczanie liczb zmiennoprzecinkowych'); writeln('---------------------------------------'); writeln('(C)2005 mgr Jerzy Walaszek I LO Tarnow'); writeln; write('Podstawa zrodlowa = '); readln(p1); if p1 in [2..36] then begin writeln; write('Mantysa = '); readln(s1); if Test(s1,p1,false) then begin write('Cecha = '); readln(s2); if Test(s2,p1,true) then begin writeln; write('Podstawa docelowa = '); readln(p2); if p2 in [2..36] then begin // Obliczamy wartość liczby. Początkowo mantysa jest równa tej // wartości, a cecha jest równa 0. m := Wartosc(s1,p1) * Potega(p1,round(Wartosc(s2,p1))); c := 0; // Normalizujemy mantysę do przedziału <1,p> if m <> 0 then begin while Abs(m) >= p2 do begin m := m / p2; inc(c); end; while Abs(m) < 1 do begin m := m * p2; dec(c); end; end; writeln; writeln(s1,'x10^',s2,'(',p1,') = ', Przelicz(m,p2),'x10^',Przelicz(c,p2),'(',p2,')'); end else writeln('Nieprawidlowa podstawa docelowa'); end else writeln('Nieprawidlowa cecha'); end else writeln('Nieprawidlowa mantysa'); end else writeln('Nieprawidlowa podstawa zrodlowa'); writeln; writeln('Nacisnij klawisz Enter...'); readln; end. |
Basic' Program przeliczający liczby zmiennoprzecinkowe. '------------------------------------------------- ' (C)2005 mgr Jerzy Wałaszek ' I Liceum Ogólnokształcące ' im. K. Brodzińskiego ' w Tarnowie '------------------------------------------------- Option Explicit On Module Module1 ' Funkcja sprawdza poprawność zapisu liczby ' Wejście: ' s - zapis liczby w postaci stałoprzecinkowej ' p - podstawa systemu ' intg - True = liczba musi być całkowita ' Wyjście: ' True, jeśli zapis jest prawidłowy '------------------------------------------------ Public Function Test(ByVal s As String, ByVal p As Integer, _ ByVal intg As Boolean) As Boolean Dim i, c As Integer Dim pc, prz As Boolean s = s.ToUpper() pc = False : prz = False For i = 0 To s.Length() - 1 Select Case s.Chars(i) Case " " : Continue For Case "-" : If pc Or prz Then Return False Else pc = True End If Case "," : If prz Or intg Then Return False Else prz = True End If Case Else c = Asc(s.Chars(i)) - 48 If c > 9 Then c -= 7 If c >= p Then Return False End Select Next Return True End Function ' Funkcja oblicza wartość liczby ' Wejście: ' s - łańcuch znakowy z zapisem liczby ' p - podstawa systemu liczbowego zapisu liczby ' Wyjście: ' wartość liczby zapisanej w s '------------------------------------------------ Public Function Wartosc(ByVal s As String, ByVal p As Integer) As Double Dim Lc, Lu, w As Double Dim c, i As UInteger Dim znak As Integer, u As Boolean s = s.ToUpper() Lc = 0 : Lu = 0 : w = 1 : u = False : znak = 1 For i = 0 To s.Length() - 1 Select Case s.Chars(i) Case "-" : znak = -1 Case "," : u = True Case Else : c = Asc(s.Chars(i)) - 48 If c > 9 Then c -= 7 If u Then Lu = p * Lu + c : w *= p Else Lc = p * Lc + c End If End Select Next Return znak * (Lc + Lu / w) End Function ' Funkcja oblicza wartość potęgi ' Wejście: ' a - liczba podnoszona do potęgi ' n - wartość wykładnika potęgowego ' Wyjście: ' a^n '------------------------------------ Public Function Potega(ByVal a As Integer, ByVal n As Integer) As Double Dim p As Double p = 1 While n > 0 p *= a : n -= 1 End While While n < 0 p /= a : n += 1 End While Return p End Function ' Funkcja znajduje zapis stałoprzecinkowy podanej liczby ' Wejście: ' L - wartość liczby ' p - podstawa systemu liczbowego zapisu liczby ' Wyjście: ' zapis liczby w systemie o podstawie p '------------------------------------------------------- Public Function Przelicz(ByVal L As Double, ByVal p As Integer) As String Dim sc, su As String Dim c As UInteger Dim Lc, Lu As Double Dim znak As Boolean znak = False : sc = "" : su = "" ' Algorytm obsługuje liczby nieujemne. Jeśli więc wartość liczby ' jest ujemna, to zapamiętujemy jej znak i zmieniamy ją na dodatnią If L < 0 Then L = -L : znak = True End If ' Wyznaczamy część całkowitą Lc oraz część ułamkową Lu. ' Część ułamkowa zostaje zaokrąglona do około 10 cyfr po ' przecinku. Lc = Int(L) : Lu = L - Lc ' Wyznaczamy zapis części całkowitej w sc Do c = Int(Lc - Int(Lc / p) * p) If c < 10 Then sc = Chr(c + 48) + sc Else sc = Chr(c + 55) + sc End If Lc = Int(Lc / p) Loop Until Lc = 0 ' Jeśli część ułamkowa jest niezerowa, to wyznaczamy jej ' zapis w su. Na końcu zapisu usuwamy zera nieznaczące If Lu > 0 Then Do Lu *= p c = Int(Lu) Lu -= c If c < 10 Then su += Chr(c + 48) Else su += Chr(c + 55) End If Loop Until (Lu = 0) Or (su.Length() = 10) su = su.TrimEnd("0") su = "," + su End If ' Jeśli konieczne, dodajemy znak liczby i całość łączymy ' w jeden zapis. If znak Then sc = "-" + sc Return sc + su End Function Sub Main() Dim m As Double Dim c, p1, p2 As Integer Dim s1, s2 As String Console.WriteLine("Przeliczanie liczb zmiennoprzecinkowych") Console.WriteLine("---------------------------------------") Console.WriteLine("(C)2005 mgr Jerzy Wałaszek I LO Tarnów") Console.WriteLine() Console.Write("Podstawa źródłowa = ") : p1 = Val(Console.ReadLine) If (p1 >= 2) And (p2 <= 36) Then Console.WriteLine() Console.Write("Mantysa = ") : s1 = Console.ReadLine If Test(s1, p1, False) Then Console.Write("Cecha = ") : s2 = Console.ReadLine If Test(s2, p1, True) Then Console.WriteLine() Console.Write("Podstawa docelowa = ") : p2 = Val(Console.ReadLine) If (p2 >= 2) And (p2 <= 36) Then ' Obliczamy wartość liczby. Początkowo mantysa jest równa tej ' wartości, a cecha jest równa 0. m = Wartosc(s1, p1) * Potega(p1, Int(Wartosc(s2, p1))) c = 0 ' Normalizujemy mantysę do przedziału <1,p> If m <> 0 Then While Math.Abs(m) >= p2 m /= p2 : c += 1 End While While Math.Abs(m) < 1 m *= p2 : c -= 1 End While End If Console.WriteLine() Console.WriteLine("{0}x10^{1}({2}) = {3}x10^{4}({5})", _ s1, s2, p1, Przelicz(m, p2), Przelicz(c, p2), p2) Else Console.WriteLine("Nieprawidłowa podstawa docelowa") End If Else Console.WriteLine("Nieprawidłowa cecha") End If Else Console.WriteLine("Nieprawidłowa mantysa") End If Else Console.WriteLine("Nieprawidłowa podstawa źródłowa") End If Console.WriteLine() Console.WriteLine("KONIEC. Naciśnij dowolny klawisz...") Console.ReadLine() End Sub End Module |
JavaScript<html> <head> </head> <body> <div align="center"> <form style="BORDER-RIGHT: #ff9933 1px outset; PADDING-RIGHT: 4px; BORDER-TOP: #ff9933 1px outset; PADDING-LEFT: 4px; PADDING-BOTTOM: 1px; BORDER-LEFT: #ff9933 1px outset; PADDING-TOP: 1px; BORDER-BOTTOM: #ff9933 1px outset; BACKGROUND-COLOR: #ffcc66" name="frmprzelicz"> <h3 id="data_out" style="text-align: center"> Przeliczanie liczb zmiennoprzecinkowych<br> w różnych systemach pozycyjnych </h3> <p style="TEXT-ALIGN: center"> (C)2005 mgr Jerzy Wałaszek I LO w Tarnowie </p> <hr> <div align="center"> <table border="0" cellpadding="4" bgcolor="#FF9933"> <tr> <td align="right">podstawa źródłowa = </td> <td> <input type="text" name="p1" size="20" value="10" style="text-align: right;"> dziesiętnie </td> </tr> <tr> <td align="right">mantysa źródłowa = </td> <td> <input type="text" name="s1" size="20" value="3,33333333" style="text-align: right"> źródłowo </td> </tr> <tr> <td align="right">cecha źródłowa = </td> <td> <input type="text" name="s2" size="20" value="-1" style="text-align: right"> źródłowo </td> </tr> <tr> <td align="right">podstawa docelowa = </td> <td> <input type="text" name="p2" size="20" value="3" style="text-align: right;"> dziesiętnie </td> </tr> </table> <p style="text-align: center"> <input type="button" value="Przelicz" name="B1" onclick="main();"> </p> <p style="TEXT-ALIGN: center" id="out_t">...</p> </div> </form> <script language=javascript> // Program przeliczający liczby zmiennoprzecinkowe. //------------------------------------------------- // (C)2005 mgr Jerzy Wałaszek // I Liceum Ogólnokształcące // im. K. Brodzińskiego // w Tarnowie //------------------------------------------------- // Funkcja sprawdza poprawność zapisu liczby // Wejście: // s - zapis liczby w postaci stałoprzecinkowej // p - podstawa systemu // intg - true = liczba musi być całkowita // Wyjście: // true, jeśli zapis jest prawidłowy //------------------------------------------------ function Test(s,p,intg) { var i,c,pc,prz; s = s.toUpperCase(); pc = prz = false; for(i = 0; i < s.length; i++) switch(s.charAt(i)) { case '-' : if(pc || prz) return(false); else pc = true; case ' ' : break; case ',' : if(prz || intg) return(false); else prz = true; break; default : c = s.charCodeAt(i) - 48; if(c > 9) c -= 7; if(c >= p) return(false); break; }; return(true); } // Funkcja oblicza wartość liczby // Wejście: // s - łańcuch znakowy z zapisem liczby // p - podstawa systemu liczbowego zapisu liczby // Wyjście: // wartość liczby zapisanej w s //------------------------------------------------ function Wartosc(s,p) { var c,i,Lc,Lu,w,znak,u; Lc = Lu = 0; znak = w = 1; u = false; s = s.toUpperCase(); for(i = 0; i < s.length; i++) switch(s.charAt(i)) { case '-' : znak = -1; case ' ' : break; case ',' : u = true; break; default : c = s.charCodeAt(i) - 48; if(c > 9) c -= 7; if(u) { Lu = p * Lu + c; w *= p; } else Lc = p * Lc + c; break; }; return(znak * (Lc + Lu / w)); } // Funkcja oblicza wartość potęgi // Wejście: // a - liczba podnoszona do potęgi // n - wartość wykładnika potęgowego // Wyjście: // a^n //------------------------------------ function Potega(a,n) { var p; p = 1; while(n > 0) { p *= a; n--; }; while(n < 0) { p /= a; n++; }; return(p); } // Funkcja znajduje zapis stałoprzecinkowy podanej liczby // Wejście: // L - wartość liczby // p - podstawa systemu liczbowego zapisu liczby // Wyjście: // zapis liczby w systemie o podstawie p //------------------------------------------------------- function Przelicz(L,p) { var sc,su,Lu,Lc,c,znak; znak = false; sc = su = ""; // Algorytm obsługuje liczby nieujemne. Jeśli więc wartość liczby // jest ujemna, to zapamiętujemy jej znak i zmieniamy ją na dodatnią if(L < 0) { L = -L; znak = true; }; // Wyznaczamy część całkowitą Lc oraz część ułamkową Lu. // Część ułamkowa zostaje zaokrąglona do około 10 cyfr po // przecinku. Lc = Math.floor(L); Lu = L - Lc; // Wyznaczamy zapis części całkowitej w sc do { c = Math.floor(Lc - Math.floor(Lc / p) * p); if(c < 10) sc = String.fromCharCode(c + 48) + sc; else sc = String.fromCharCode(c + 55) + sc; Lc = Math.floor(Lc / p); } while(Lc); // Jeśli część ułamkowa jest niezerowa, to wyznaczamy jej // zapis w su. Na końcu zapisu usuwamy zera nieznaczące if(Lu) { do { Lu = Lu * p; c = Math.floor(Lu); Lu = Lu - c; if(c < 10) su += String.fromCharCode(c + 48); else su += String.fromCharCode(c + 55); } while(Lu && su.length < 10); while((su != "") && (su.charAt(su.length - 1) == '0')) su = su.substring(0,su.length-1); su = "," + su; }; // Jeśli konieczne, dodajemy znak liczby i całość łączymy // w jeden zapis. if(znak) sc = "-" + sc; return(sc + su); } //********************** //*** PROGRAM GŁÓWNY *** //********************** function main() { var m,c,p1,p2,s1,s2,t; p1 = parseInt(document.frmprzelicz.p1.value); if(!isNaN(p1) && (p1 > 1) && (p1 < 37)) { s1 = document.frmprzelicz.s1.value; if(Test(s1,p1,false)) { s2 = document.frmprzelicz.s2.value; if(Test(s2,p1,true)) { p2 = parseInt(document.frmprzelicz.p2.value); if(!isNaN(p2) && (p2 > 1) && (p2 < 37)) { // Obliczamy wartość liczby. Początkowo mantysa jest równa tej // wartości, a cecha jest równa 0. m = Wartosc(s1,p1) * Potega(p1,Wartosc(s2,p1)); c = 0; // Normalizujemy mantysę do przedziału <1/p,1) if(m) { while(Math.abs(m) >= p2) { m /= p2; c++; }; while(Math.abs(m) < 1) { m *= p2; c--; }; }; t = s1 + " x 10<sup>" + s2 + "</sup><sub>(" + p1 + ")</sub> = " + Przelicz(m,p2) + " x 10<sup>" + Przelicz(c,p2) + "</sup><sub>(" + p2 + ")</sub>"; } else t = "<font color=Red><b>Nieprawidlowa podstawa docelowa</b></font>"; } else t = "<font color=Red><b>Nieprawidłowa cecha</b></font>"; } else t = "<font color=Red><b>Nieprawidłowa mantysa</b></font>"; } else t = "<font color=Red><b>Nieprawidłowa podstawa źródłowa</b></font>"; document.getElementById("out_t").innerHTML = t; return 0; } </script> </div> </body> </html> |
Wynik: |
Przeliczanie liczb
zmiennoprzecinkowych --------------------------------------- (C)2005 mgr Jerzy Wałaszek I LO Tarnów Podstawa źródłowa = 10 Mantysa = 23,56 Cecha = -2 Podstawa docelowa = 2 23,56x10^-2(10) = 1,111000101x10^-11(2) KONIEC. Naciśnij dowolny klawisz... |
Oblicz wartość dziesiętną następujących liczb zmiennoprzecinkowych (pamiętaj, że wszystkie składniki liczby są zapisane w tym samym systemie pozycyjnym). Jeśli wynik jest ułamkowy, to wprowadź go w postaci części całkowitej i ułamka właściwego. Pomiędzy częścią całkowitą a ułamkiem musisz umieścić dokładnie jedną spację, np. 356 15/16.
Przelicz podane liczby dziesiętne kolejno na zmiennoprzecinkowy system szesnastkowy, ósemkowy i dwójkowy. Wyniki przedstaw w postaci znormalizowanej.
1 · 105 5,12 · 102 27,25 · 10-2
W rozdziale przedstawiliśmy podstawową wiedzę związaną z pozycyjnymi systemami liczenia, którą musi sobie przyswoić każdy informatyk. Chociaż nie ograniczaliśmy się do konkretnych systemów liczbowych (celowo!), w praktyce będziemy spotykać tylko cztery systemy pozycyjne: dwójkowy, ósemkowy, dziesiętny oraz szesnastkowy. Pozostałe mają znaczenie marginalne.
Ważne jest, abyście zrozumieli, iż pewne prawidłowości zachodzą we wszystkich systemach pozycyjnych i poznanie ich znacznie ułatwia wszelkie przeliczenia. Dla człowieka najbardziej zrozumiałym systemem jest system dziesiętny, dla komputera z kolei jest on niewygodny i stosuje się tutaj system dwójkowy, którym zajmiemy się dokładniej w dalszych rozdziałach naszego artykułu. Jednakże będziemy się ciągle odwoływać do materiału zawartego w tym rozdziale.
Zobacz dalej...
Wartość liczby pozycyjnej | Schemat Hornera | Przeliczenia na inny zapis pozycyjny | Wartość liczby stałoprzecinkowej | Przeliczanie na zapis stałoprzecinkowy
![]() |
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2023 mgr Jerzy Wałaszek |
Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone
pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.