Login lub e-mail Hasło   

Wartość liczby stałoprzecinkowej

Odnośnik do oryginalnej publikacji: http://www.i-lo.tarnow.pl/edu/inf/alg/nu(...)ex.html
Dotychczasowe rozważania dotyczyły liczb naturalnych. Zapis pozycyjny można w prosty sposób rozszerzyć na liczby ułamkowe wprowadzając pozycje o wagach ułamkowych. Przy...
Wyświetlenia: 4.294 Zamieszczono 29/10/2006

Dotychczasowe rozważania dotyczyły liczb naturalnych. Zapis pozycyjny można w prosty sposób rozszerzyć na liczby ułamkowe wprowadzając pozycje o wagach ułamkowych. Przyjrzyjmy się liczbie dziesiętnej:

Wagi pozycji   103 102 101 100   10-1 10-2 10-3 10-4 10-5

Cyfry zapisu  

 3   5   7   9  ,  8   2   9   1   4 
Numery pozycji   3 2 1 0   -1 -2 -3 -4 -5
  Część
całkowita
  Część
ułamkowa

Liczba stałoprzecinkowa może być potraktowana jako złożenie dwóch liczb - części całkowitej oraz części ułamkowej rozdzielone przecinkiem. Umówmy się, iż pozycje ułamkowe będziemy numerować kolejnymi liczbami ujemnymi. Przy takiej umowie wagi pozycji ułamkowych wciąż będą równe podstawie podniesionej do potęgi o wartości numeru pozycji. Zasada obliczania wartości liczby stałoprzecinkowej jest identyczna do poznanej wcześniej zasady: wartość liczby stałoprzecinkowej jest równa sumie iloczynów jej cyfr przez wagi pozycji tych cyfr. W systemie pozycyjnym o podstawie innej niż dziesięć jest tak samo.

 

Obliczyć wartość liczby stałoprzecinkowej 213,132(4).

213,132(4) = 2 x 42 + 1 x 41 + 3 x 40 + 1 x 4-1 + 3 x 4-2 + 2 x 4-3
213,132(4) = 2
x 16 + 1 x 4 + 3 x 1 + 1 x 1/4 + 3 x 1/16 + 2 x 1/64
213,132(4) = 32 + 4 + 3 + 1/4 + 3/16 + 2/64
213,132(4) = 39 + 16/64 + 12/64 + 2/64
213,132(4) = 39 30/64

Obliczyć wartość liczby stałoprzecinkowej 537,462(8).

537,462(8) = 5 x 82 + 3 x 81 + 7 x 80 + 4 x 8-1 + 6 x 8-2 + 2 x 8-3
537,462(8) = 5
x 64 + 3 x 8 + 7 x 1 + 4 x 1/8 + 6 x 1/64 + 2 x 1/512
537,462(8) = 320 + 24 + 7 + 4/8 + 6/64 + 2/512
537,462(8) = 351 + 256/512 + 48/512 + 2/512
537,462(8) = 351 306/
512

Obliczenie wartości liczby stałoprzecinkowej według podstawowego wzoru wymaga obliczeń na ułamkach. Z doświadczenia wiem, iż tutaj uczniowie zwykle popełniają najwięcej pomyłek (nawet w klasie matematycznej). Podam zatem prosty sposób znajdowania wartości części ułamkowej bez sumowania ułamków. Najpierw przyjrzyjmy się kilku liczbom dziesiętnym:

0,3  = 3/10
0,35  = 35/100
0,357  = 357/1000
0,3579  = 3579/10000

Czy zauważasz tutaj pewną prawidłowość? Jeśli potraktujemy część ułamkową jako liczbę całkowitą, to wartość części ułamkowej będzie po prostu iloczynem tej liczby i wagi pozycji ostatniej cyfry zapisu stałoprzecinkowego. W powyższych przykładach waga pozycji ostatniej cyfry wynosi kolejno 10-1 = 1/10, 10-2 = 1/100, 10-3 = 1/1000 i 10-4 = 1/10000. W innych systemach pozycyjnych zasada ta wciąż obowiązuje, gdyż system dziesiętny nie jest przecież żadnym wyróżnionym systemem pozycyjnym.

 

Oblicz wartość liczby stałoprzecinkowej 0,4231(5).

Część całkowita wynosi 0. Część ułamkową potraktujemy jako liczbę całkowitą, obliczymy jej wartość i pomnożymy ją przez wagę ostatniej cyfry zapisu stałoprzecinkowego, czyli przez 5-4 = 1/625.

4231(5) = 4 x 53 + 2 x 52 + 3 x 51 + 1 x 50
4231(5) = 4
x 125 + 2 x 25 + 3 x 5 + 1 x 1
4231(5) = 500 + 50 + 15 + 1
4231(5) = 566

Zatem 0,4231(5) = 566 x 1/625 = 566/625.

Sprawdzamy:

0,4231(5) = 0 x 50 + 4 x 5-1 + 2 x 5-2 + 3 x 5-3 + 1 x 5-4
0,4231(5) = 0
x 1 + 4 x 1/5 + 2 x 1/25 + 3 x 1/125 + 1 x 1/625
0,4231(5) = 0 + 4/5 + 2/25 + 3/125 + 1/625
0,4231(5) = 500/625 + 50/625 + 15/625 + 1/625
0,4231(5) = 566/625
.

Podsumujmy podane dotychczas informacje w formie algorytmu.

Dane wejściowe

p - podstawa docelowego systemu pozycyjnego, p N,  p {2,3,...,10}
s - tekst zawierający ciąg znaków ASCII przedstawiających poprawny zapis liczby.

Dane wyjściowe

Liczba L będąca wartością liczby o podstawie p i zapisanej w postaci ciągu znaków s. L R+

Zmienne pomocnicze i funkcje

w - odwrotność wagi pozycji ostatniej cyfry, w N
u - informuje o napotkaniu przecinka, u {true, false}
i - numer kolejnego znaku w zmiennej s, i N
kod(znak) - funkcja zwraca kod ASCII znaku
długość(tekst) - zwraca liczbę znaków zawartych w tekście

krok 1: Czytaj p i s
krok 2: L 0 w pu false
krok 3: Dla i = 1,2,...,długość(s) wykonuj kroki 4...6.
krok 4:     Jeśli s[i] = ",", to u true i idź do kroku 7
krok 5:     c kod(s[i]) - kod("0")
krok 6:     Jeśli u = true, to L L + c : w;   w w x p. Inaczej L L x p + c
krok 7: Pisz L i zakończ algorytm

Odczytujemy podstawę p oraz zapis liczby w zmiennej łańcuchowej s. Nasz algorytm zakłada, iż kolejne znaki w s są umieszczone na pozycjach numerowanych od 1 (w językach C++, Python oraz JavaScript znaki są numerowane od pozycji 0 - należy zatem zastosować odpowiednią poprawkę).

Algorytm wykorzystuje schemat Hornera do wyznaczenia wartości części całkowitej oraz wzór podstawowy do wyznaczenia części ułamkowej liczby. Zwróć uwagę, iż zastosowany tutaj schemat Hornera różni się nieco od podanego wcześniej. Różnica polega na tym, iż rozpoczynamy od ustawienia wartości wyznaczanej liczby L na 0 (a nie na wartość pierwszej cyfry). Dzięki temu podejściu znacznie upraszcza się algorytm.

Zmienna u pełni rolę znacznika przecinka (u jak ułamek). Początkowo ustawiamy ją na false, co spowoduje, iż algorytm będzie wyznaczał wartość części całkowitej liczby.

Rozpoczynamy pętlę iteracyjną sterowaną przez zmienną i. Zadaniem tej pętli jest przeglądnięcie wszystkich znaków w odczytanym tekście s. Gdy pętla się zakończy w L mamy obliczoną wartość liczby. Wyświetlamy ją i kończymy algorytm.

Wewnątrz pętli najpierw sprawdzamy, czy bieżącym znakiem jest przecinek. Jeśli tak, to ustawiamy na true znacznik przecinka u, co spowoduje, iż algorytm będzie wyznaczał wartość części ułamkowej liczby. Po ustawieniu tego znacznika rozpoczynamy kolejny obieg pętli.

Jeśli bieżącym znakiem nie jest przecinek, to zakładamy, iż jest nim cyfra. Wyznaczamy jej wartość i wynik umieszczamy w zmiennej c.

Następnie w zależności od stanu logicznego znacznika u wyliczamy wartość części całkowitej (u=false) lub ułamkowej (u=true). W części całkowitej stosujemy schemat Hornera. W części ułamkowej dzielimy cyfrę przez odwrotność wagi jej pozycji (zmienna w) i dodajemy do wyliczanej wartości liczby L. Po tej operacji wyliczamy odwrotność wagi następnej pozycji ułamkowej.

Kontynuujemy kolejny obieg pętli aż do przetworzenia wszystkich znaków w s.


   
   
   

Poniższe, przykładowe programy są praktyczną realizacją omawianego w tym rozdziale algorytmu. Zapewne można je napisać bardziej efektywnie. To już twoje zadanie. Dokładny opis stosowanych środowisk programowania znajdziesz we wstępie. Programy przed opublikowaniem w serwisie edukacyjnym zostały dokładnie przetestowane. Jeśli jednak znajdziesz jakąś usterkę (co zawsze może się zdarzyć), to prześlij o niej informację do autora. Pozwoli to ulepszyć nasze artykuły. Będziemy Ci za to wdzięczni.

 
       

Na podstawie algorytmu tworzymy programy wyznaczające wartość dziesiętną liczby stałoprzecinkowej zapisanej w systemie pozycyjnym o podstawie od 2 do 10. Zwróć uwagę, iż algorytm nie sprawdza poprawności danych wprowadzonych przez użytkownika.

Wydruk z uruchomionego programu
Obliczanie  wartości  liczby stałoprzecinkowej
zapisanej w systemie pozycyjnym o podstawie p
----------------------------------------------
(C)2005 mgr Jerzy Wałaszek I LO Tarnów

Podaj p (2..10) = 8

Podaj liczbę L = 77,777

77,777(8) = 63,998046875(10)

KONIEC. Naciśnij dowolny klawisz...
Microsoft Visual Basic 2005 Express Edition

 

Borland
Delphi 7.0
Personal
Edition
// obliczanie wartości liczby stałoprzecinkowej
// zapisanej w systemie pozycyjnym o podstawie
// równej od 2 do 10
//---------------------------------------------
// (C)2005 mgr Jerzy Wałaszek
// I Liceum Ogólnokształcące
// im. K. Brodzińskiego
// w Tarnowie
//---------------------------------------------

program lspoz;

{$APPTYPE CONSOLE}

var
s : string;
c,i,w,p : cardinal;
L : real;
u : boolean;
begin
writeln('Obliczanie wartosci liczby staloprzecinkowej');
writeln('zapisanej w systemie pozycyjnym o podstawie p');
writeln('----------------------------------------------');
writeln('(C)2005 mgr Jerzy Walaszek I LO Tarnow');
writeln;
write('Podaj p (2..10) = '); readln(p);
writeln;
write('Podaj liczbe L = '); readln(s);
writeln;
L := 0; u := false; w := p;
for i := 1 to length(s) do
begin
if
s[i] = ',' then
u := true
else
begin

c := ord(s[i]) - ord('0');
if u then
begin

L := L + c / w;
w := w * p;
end
else
L := L * p + c
end
end;
writeln(s,'(',p,') = ',L:0:10);
writeln;
writeln('Nacisnij klawisz ENTER...');
readln;
end.
Borland
C++ Builder
6.0
Personal
Edition
// obliczanie wartości liczby stałoprzecinkowej
// zapisanej w systemie pozycyjnym o podstawie
// równej od 2 do 10
//---------------------------------------------
// (C)2005 mgr Jerzy Wałaszek
// I Liceum Ogólnokształcące
// im. K. Brodzińskiego
// w Tarnowie
//---------------------------------------------

#include <iostream>
#include <iomanip>
#include <string>

using namespace std;

main()
{
string s;
unsigned c,i,p,w;
bool u;
double L;
char z[1];

cout.precision(10); // 10 cyfr po przecinku
cout.setf(ios::fixed); // format stałoprzecinkowy

cout << "Obliczanie wartosci liczby staloprzecinkowej\n"
"zapisanej w systemie pozycyjnym o podstawie p\n"
"----------------------------------------------\n"
"(C)2005 mgr Jerzy Walaszek I LO Tarnow\n\n"
"Podaj p (2..10) = "
;
cin >> p;
cout << "\nPodaj liczbe L = ";
getline(cin,s);
getline(cin,s);
L = 0; w = p; u = false;
for(i = 0; i < s.length(); i++)
{
if(s[i] == ',')
u = true;
else
{
c = s[i] - int('0');
if(u)
{
L += double(c) / w; w *= p;
}
else L = L * p + c;
}
}
cout << endl << s << "(" << p << ") = " << L
<< "\n\nNacisnij ENTER...\n";
cin.getline(z,1);
}
Microsoft
Visual
Basic 2005
Express
Edition
' obliczanie wartości liczby stałoprzecinkowej
' zapisanej w systemie pozycyjnym o podstawie
' równej od 2 do 10
'---------------------------------------------
' (C)2005 mgr Jerzy Wałaszek
' I Liceum Ogólnokształcące
' im. K. Brodzińskiego
' w Tarnowie
'---------------------------------------------

Option Explicit On

Module
Module1

Sub Main()

Dim s As String
Dim
c, i, w, p As UInteger
Dim
L As Double
Dim
u As Byte

Console.WriteLine("Obliczanie wartości liczby stałoprzecinkowej")
Console.WriteLine("zapisanej w systemie pozycyjnym o podstawie p")
Console.WriteLine("----------------------------------------------")
Console.WriteLine("(C)2005 mgr Jerzy Wałaszek I LO Tarnów")
Console.WriteLine()
Console.Write("Podaj p (2..10) = ") : p = Val(Console.ReadLine)
Console.WriteLine()
Console.Write("Podaj liczbę L = ") : s = Console.ReadLine
Console.WriteLine()
L = 0 : w = p : u = 0
For i = 0 To s.Length() - 1
If s.Chars(i) = "," Then
u = 1
Else
c = Asc(s.Chars(i)) - 48
If u = 1 Then
L += c / w : w *= p
Else
L = L * p + c
End If
End If
Next

Console.WriteLine("{0}({1}) = {2}(10)", s, p, L)
Console.WriteLine()
Console.WriteLine("KONIEC. Naciśnij dowolny klawisz...")
Console.ReadLine()

End Sub

End Module
Python
# -*- coding: cp1250 -*-
# obliczanie wartości liczby stałoprzecinkowej
# zapisanej w systemie pozycyjnym o podstawie
# równej od 2 do 10
#---------------------------------------------
# (C)2005 mgr Jerzy Wałaszek
# I Liceum Ogólnokształcące
# im. K. Brodzińskiego
# w Tarnowie
#---------------------------------------------

print " Obliczanie wartosci liczby staloprzecinkowej "
print "zapisanej w systemie pozycyjnym o podstawie p"
print "----------------------------------------------"
print "(C)2005 mgr Jerzy Walaszek I LO Tarnow"
print
p = int(raw_input("Podaj p (2..10) = "))
print
s = raw_input("Podaj liczbe L = ")
print
L = 0.0
u = 0
w = p
for i in range(len(s)):
if s[i] == ",": u = 1
else:
c = ord(s[i]) - ord("0")
if u: L, w = L + float(c) / w, w * p
else: L = L * p + c
print "%s(%d) = %f" % (s, p, L)
print
raw_input("Nacisnij klawisz ENTER...")
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">
Obliczanie wartości liczby stałoprzecinkowej<br>
zapisanej w systemie pozycyjnym o podstawie p
</h3>
<p style=
"TEXT-ALIGN: center">
(C)2005 mgr Jerzy Wałaszek&nbsp;&nbsp; I LO w Tarnowie
</p>
<hr>
<div align=
"center">
<table border=
"0" cellpadding="4" style="border-collapse: collapse">
<tr>
<td align=
"right">Podstawa (2...10) =</td>
<td>
<input value=
"4" name="inp_p" size="20" style="text-align: right">
</td>
</tr>
<tr>
<td align=
"right">Liczba =</td>
<td>
<input value=
"23,332" name="inp_l" size="20" style="text-align: right">
</td>
</tr>
</table>
</div>
<p style=
"TEXT-ALIGN: center">
<input onclick=
"main();" type="button" value="Oblicz wartość" name="B1">
</p>
<p id=
"out_t" style="TEXT-ALIGN: center">...</p>
</form>

<script language=javascript>


// obliczanie wartości liczby stałoprzecinkowej
// zapisanej w systemie pozycyjnym o podstawie
// równej od 2 do 10
//---------------------------------------------
// (C)2005 mgr Jerzy Wałaszek
// I Liceum Ogólnokształcące
// im. K. Brodzińskiego
// w Tarnowie
//---------------------------------------------

function main()
{
var s,c,i,L,p,t,u,w;

p = parseInt(document.frmprzelicz.inp_p.value);
s = document.frmprzelicz.inp_l.value;
if(isNaN(p) || (s==""))
t = "<font color=Red><b>Złe dane</b></font>";
else
{
L = 0.0; w = p; u = false;
for(i = 0; i < s.length; i++)
{
if(s.charAt(i) == ',')
u = true;
else
{
c = s.charCodeAt(i) - 48;
if(u)
{
L += c / w; w *= p;
}
else L = L * p + c;
}
}
t = s + "<sub>(" + p + ")</sub> = " + L;
};
document.getElementById("out_t").innerHTML = t;
}

</script>
</div>
</body>
</html>

Dokument ten rozpowszechniany jest zgodnie z zasadami licencji
GNU Free Documentation License.

Podobne artykuły


16
komentarze: 5 | wyświetlenia: 9006
9
komentarze: 0 | wyświetlenia: 2784
49
komentarze: 18 | wyświetlenia: 64976
12
komentarze: 3 | wyświetlenia: 29779
37
komentarze: 9 | wyświetlenia: 28519
11
komentarze: 2 | wyświetlenia: 33152
7
komentarze: 1 | wyświetlenia: 34648
17
komentarze: 4 | wyświetlenia: 14179
15
komentarze: 5 | wyświetlenia: 32760
13
komentarze: 2 | wyświetlenia: 22961
12
komentarze: 2 | wyświetlenia: 18505
11
komentarze: 1 | wyświetlenia: 86405
11
komentarze: 1 | wyświetlenia: 10472
10
komentarze: 1 | wyświetlenia: 34969
 
Autor
Artykuł




Brak wiadomości


Dodaj swoją opinię
W trosce o jakość komentarzy wymagamy od użytkowników, aby zalogowali się przed dodaniem komentarza. Jeżeli nie posiadasz jeszcze swojego konta, zarejestruj się. To tylko chwila, a uzyskasz dostęp do dodatkowych możliwości!
 

© 2005-2018 grupa EIOBA. Wrocław, Polska