JustPaste.it

Przeliczanie na zapis stałoprzecinkowy

320a2f017797b13d87c4b7cc463f67eb.gif

Nasz problem polega na znalezieniu reprezentacji danej liczby dziesiętnej w docelowym systemie pozycyjnym o podstawie p. Część całkowitą przeliczamy wg poznanych zasad. Znalezienie kolejnych cyfr zapisu części ułamkowej w systemie docelowym jest zadziwiająco proste. Rozpiszmy wzór na część ułamkową liczby:

Lu = C-1 p-1 + C-2 p-2 + C-3 p-3 + ... + C-m+1 p-m+1 + C-m p-m

gdzie:

Lu - wartość części ułamkowej zapisu liczby
Ci , i = -1,-2,...,-m - kolejne cyfry zapisu części ułamkowej
p - podstawa systemu pozycyjnego zapisu liczby stałoprzecinkowej
m - liczba cyfr części ułamkowej

Pomnóżmy część ułamkową przez podstawę p. Otrzymamy:

Lu x p = (C-1 p-1 + C-2 p-2 + C-3 p-3 + ... + C-m+1 p-m+1 + C-m p-m) p
Lu
x p = C-1 p-1p + C-2 p-2p + C-3 p-3p + ... + C-m+1 p-m+1p + C-m p-mp
Lu
x p = C-1 p0 + C-2 p-1 + C-3 p-2 + ... + C-m+1 p-m+2 + C-m p-m+1

Co uzyskaliśmy w wyniku? Wynikowa liczba ma przesunięte wszystkie cyfry zapisu o jedną pozycję w lewo. Pierwsza cyfra ułamkowa stała się teraz cyfrą całkowitą. Aby ją wydobyć wystarczy wziąć część całkowitą wyniku mnożenia przez p. Za nową część ułamkową przyjmujemy część ułamkową wyniku mnożenia. Działanie to będziemy kontynuowali dotąd, aż wydobędziemy zadaną ilość cyfr ułamkowych.

2d6b1200f7f7da272b9844759e82312d.gif

 

Znaleźć zapis liczby dziesiętnej 234,13(10) w systemie czwórkowym z dokładnością do 10 cyfr po przecinku.

Rozdzielamy liczbę na część całkowitą i ułamkową:

Lc = 234, Lu = 0,13

Wyznaczamy cyfry zapisu części całkowitej w systemie czwórkowym:

234 div 4 =  58  i reszta 2
58 div 4 =  14  i reszta 2
14 div 4 =  3  i reszta 2
3 div 4 =  0  i reszta 3 - koniec

234(10) = 3222(4)

Teraz wyznaczamy 10 kolejnych cyfr części ułamkowej

0,13 x 4 =  0,52  - cyfra 0
0,52 x 4 =  2,08  - cyfra 2
0,08 x 4 =  0,32  - cyfra 0
0,32 x 4 =  1,28  - cyfra 1
0,28 x 4 =  1,12  - cyfra 1
0,12 x 4 =  0,48  - cyfra 0
0,48 x 4 =  1,92  - cyfra 1
0,92 x 4 =  3,68  - cyfra 3
0,68 x 4 =  2,72  - cyfra 2
0,72 x 4 =  2,88  - cyfra 2 - koniec, obliczyliśmy zadaną ilość cyfr po przecinku

0,13(10) = 0,0201101322...(4).

Łączymy wyznaczone cyfry części całkowitej i ułamkowej otrzymując wynik:

234,13(10) = 3222,0201101322...(4).

Zwróć uwagę, iż wyznaczając cyfry ułamkowe nie otrzymaliśmy wyniku równego 0. Oznacza to, iż znalezione rozwinięcie zapisu liczby w systemie czwórkowym jest przybliżone - z dokładnością do 10 cyfr ułamkowych systemu czwórkowego. Fakt ten sygnalizujemy w zapisie trzema kropeczkami za ostatnią cyfrą.

208efaee3cee303680856b2e19a2f5ce.gif

Dane wejściowe

L - liczba rzeczywista, której reprezentację wyznaczamy w systemie docelowym,  L 38e14c88d67f65ca64f14b718944de20.gif R+
p - podstawa docelowego systemu pozycyjnego,  p 38e14c88d67f65ca64f14b718944de20.gif N,  p 38e14c88d67f65ca64f14b718944de20.gif {2,3,...,10}
m - liczba cyfr części ułamkowej w systemie docelowym,  m 38e14c88d67f65ca64f14b718944de20.gif N

Dane wyjściowe

Ciąg znaków ASCII reprezentujących zapis liczby L w systemie pozycyjnym o podstawie p.

Zmienne pomocnicze i funkcje

Lc - część całkowita liczby L,   Lc 38e14c88d67f65ca64f14b718944de20.gif N
Lu - część ułamkowa liczby L,   Lu 38e14c88d67f65ca64f14b718944de20.gif R+ + {0}
s - łańcuch znaków, w którym składowane są kolejne cyfry zapisu liczby
c - wartość wyliczonej cyfry, c 38e14c88d67f65ca64f14b718944de20.gif N + {0}
znak(kod) - zwraca znak ASCII o podanym kodzie

e44e45bbfeddb28f8be2558cfa8f8bf4.gif

krok 1: Czytaj L, p, m
krok 2: Lc 132dc69d7ade9b6e00a2b78fd8615b30.gif [L];   Lu 132dc69d7ade9b6e00a2b78fd8615b30.gif L - Lc;   s 132dc69d7ade9b6e00a2b78fd8615b30.gif ""
krok 3:     c 132dc69d7ade9b6e00a2b78fd8615b30.gif Lc mod p
krok 4:     s 132dc69d7ade9b6e00a2b78fd8615b30.gif znak(c + 48) + s
krok 5:     Lc 132dc69d7ade9b6e00a2b78fd8615b30.gif Lc div p
krok 6: Jeśli Lc 17dff529ed7553db815c4775e08b6a96.gif 0, idź do kroku 3
krok 7: s 132dc69d7ade9b6e00a2b78fd8615b30.gif s + ","
krok 8:     Jeśli m c279ef2d847bccd45a954994fc246c99.gif 0, to pisz s i zakończ algorytm.
krok 9:     Lu 132dc69d7ade9b6e00a2b78fd8615b30.gif Lu x p
krok 10:     c 132dc69d7ade9b6e00a2b78fd8615b30.gif [Lu]
krok 11:     s 132dc69d7ade9b6e00a2b78fd8615b30.gif s + znak(c + 48)
krok 12: m 132dc69d7ade9b6e00a2b78fd8615b30.gif m - 1 i idź do kroku 8

53c33edc7d2c47f6b2f5d0d18ab90bdd.gif

 

Odczytujemy liczbę L, podstawę docelowego systemu pozycyjnego p, na który mamy przeliczyć liczbę L oraz ilość cyfr po przecinku m, które mają się pojawić w rozwinięciu zapisu liczby L w systemie pozycyjnym o podstawie p.

Liczbę L rozdzielamy na dwie części - całkowitą Lc oraz ułamkową Lu.

W pierwszej pętli wyznaczamy kolejne cyfry (od tyłu) zapisu części całkowitej Lc w docelowym systemie pozycyjnym. Zastosowany tutaj algorytm opisaliśmy w rozdziale o przeliczaniu liczby na inny system pozycyjny.

Po wyznaczeniu tych cyfr dodajemy do zapisu znak przecinka.

Druga pętla wyznacza m cyfr rozwinięcia części ułamkowej Lu. Lu mnożymy przez podstawę p. Cyfrę otrzymujemy z części całkowitej wyniku tego iloczynu. Otrzymaną cyfrę zamieniamy na znak ASCII i dopisujemy do zmiennej s. Za nową część ułamkową Lu przyjmujemy część ułamkową iloczynu poprzedniej części ułamkowej Lu i podstawy p. Zmniejszamy licznik cyfr m o 1. Pętla jest kontynuowana aż do wyzerowania tego licznika.

Po zakończeniu obu pętli w zmiennej s mamy kompletny zapis liczby L w systemie pozycyjnym o podstawie p. Wypisujemy zawartość tej zmiennej i kończymy algorytm.

Zwróć uwagę, iż dla prostoty algorytm nie sprawdza poprawności wprowadzonych przez użytkownika danych. Zaproponuj odpowiednią modyfikację algorytmu, aby takie sprawdzenie było wykonywane. Szczególnie niebezpieczna jest sytuacja, gdy podstawa docelowego systemu pozycyjnego p otrzyma wartość 1. Wtedy pętla pierwsza stanie się pętlą nieskończoną (dlaczego?) i program po prostu się zawiesi.


 

bfe26a94661c88826827baa8563e5a67.gif
DLA
GENIUSZA

14b7f90150fdd9ba6128f872837e1de9.gif

80009acb8ed134e84a20f41117e30b17.gif    
   
   

c8ac4da5816ac53afeb18bb9a8baa425.gif

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 przeliczające liczbę w zapisie dziesiętnym na zapis w systemie pozycyjnym o podstawie od 2 do 10. Przy wprowadzaniu liczby zamiast przecinka używaj kropki do oddzielenia części całkowitej od ułamkowej - wymaga tego biblioteka we/wy języka Pascal.

Wydruk z uruchomionego programu
Przeliczanie stałoprzecinkowej liczby dziesiętnej
na zapis w systemie pozycyjnym o podstawie 2...10
-------------------------------------------------
(C)2005 mgr Jerzy Wałaszek I LO Tarnów

Podaj liczbę L = 17.127

Podaj p (2..10) = 2

Cyfry ułamkowe = 10

17,127(10) = 10001,0010000010(2)

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

 

Borland
Delphi 7.0
Personal
Edition
// Przeliczanie dziesiętnej liczby stałoprzecinkowej
// na zapis w systemie pozycyjnym o podstawie 2...10
//--------------------------------------------------
// (C)2005 mgr Jerzy Wałaszek
// I Liceum Ogólnokształcące
// im. K. Brodzińskiego
// w Tarnowie
//--------------------------------------------------

program pldz;

{$APPTYPE CONSOLE}

var
s : string;
L,Lu : real;
p,c,Lc,m : cardinal;
begin
writeln('Przeliczanie staloprzecinkowej liczby dziesietnej');
writeln('na zapis w systemie pozycyjnym o podstawie 2...10');
writeln('-------------------------------------------------');
writeln('(C)2005 mgr Jerzy Walaszek I LO Tarnow');
writeln;
write('Podaj liczbe L = '); readln(L);
writeln;
write('Podaj p (2..10) = '); readln(p);
writeln;
write('Cyfry ulamkowe = '); readln(m);
writeln;
Lc := trunc(L); Lu := L - Lc;
s := '';
repeat
c := Lc mod p;
s := char(c + 48) + s;
Lc := Lc div p;
until Lc = 0;
s := s + ',';
while m > 0 do
begin

Lu := Lu * p;
c := trunc(Lu);
s := s + char(c + 48);
Lu := Lu - c;
dec(m);
end;
writeln(L:0:10,'(10) = ',s,'(',p,')');
writeln;
writeln('Nacisnij klawisz ENTER...');
readln;
end.
Borland
C++ Builder
6.0
Personal
Edition
// Przeliczanie dziesiętnej liczby stałoprzecinkowej
// na zapis w systemie pozycyjnym o podstawie 2...10
//--------------------------------------------------
// (C)2005 mgr Jerzy Wałaszek
// I Liceum Ogólnokształcące
// im. K. Brodzińskiego
// w Tarnowie
//--------------------------------------------------

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

using namespace std;

main()
{
string s;
double L,Lu;
unsigned p,c,Lc,m;
char z[1];

cout.precision(10); // 10 cyfr po przecinku
cout.setf(ios::fixed); // format stałoprzecinkowy
cout << "Przeliczanie staloprzecinkowej liczby dziesietnej\n"
"na zapis w systemie pozycyjnym o podstawie 2...10\n"
"-------------------------------------------------\n"
"(C)2005 mgr Jerzy Walaszek I LO Tarnow\n\n"
"Podaj liczbe L = "
;
cin >> L;
cout << "\nPodaj p (2..10) = ";
cin >> p;
cout << "\nCyfry ulamkowe = ";
cin >> m;
cout << endl;
Lc = (unsigned) floor(L); Lu = L - Lc;
s = "";
do
{
c = Lc % p;
s = (char) (c + 48) + s;
Lc = Lc / p;
} while(Lc);
s += ",";
while(m)
{
Lu *= p;
c = (unsigned) floor(Lu);
s += (char) (c + 48);
Lu -= c;
m--;
};
cout << L << "(10) = " << s << "(" << p
<< ")\n\nNacisnij ENTER...\n";
cin.getline(z,1);
cin.getline(z,1);
}
Microsoft
Visual
Basic 2005
Express
Edition
' Przeliczanie dziesiętnej liczby stałoprzecinkowej
' na zapis w systemie pozycyjnym o podstawie 2...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
L, Lu As Double
Dim
p, c, Lc, m As UInteger

Console.WriteLine("Przeliczanie stałoprzecinkowej liczby dziesiętnej")
Console.WriteLine("na zapis w systemie pozycyjnym o podstawie 2...10")
Console.WriteLine("-------------------------------------------------")
Console.WriteLine("(C)2005 mgr Jerzy Wałaszek I LO Tarnów")
Console.WriteLine()
Console.Write("Podaj liczbę L = ") : L = Val(Console.ReadLine)
Console.WriteLine()
Console.Write("Podaj p (2..10) = ") : p = Val(Console.ReadLine)
Console.WriteLine()
Console.Write("Cyfry ułamkowe = ") : m = Val(Console.ReadLine)
Console.WriteLine()
Lc = Int(L) : Lu = L - Lc
s = ""
Do
c = Lc Mod p
s = Chr(c + 48) + s
Lc \= p
Loop Until Lc = 0
s += ","
While m > 0
Lu *= p
c = Int(Lu)
s += Chr(c + 48)
Lu -= c
m -= 1
End While
Console.WriteLine("{0}(10) = {1}({2})", L, s, p)
Console.WriteLine()
Console.WriteLine("KONIEC. Naciśnij dowolny klawisz...")
Console.ReadLine()

End Sub

End Module
Python
# -*- coding: cp1250 -*-
# Przeliczanie dziesiętnej liczby stałoprzecinkowej
# na zapis w systemie pozycyjnym o podstawie 2...10
#--------------------------------------------------
# (C)2005 mgr Jerzy Wałaszek
# I Liceum Ogólnokształcące
# im. K. Brodzińskiego
# w Tarnowie
#--------------------------------------------------

import math

print "Przeliczanie staloprzecinkowej liczby dziesietnej"
print "na zapis w systemie pozycyjnym o podstawie 2...10"
print "-------------------------------------------------"
print "(C)2005 mgr Jerzy Walaszek I LO Tarnow"
print
L = float(raw_input("Podaj liczbe L = "))
print
p = int(raw_input("Podaj p (2..10) = "))
print
m = int(raw_input("Cyfry ulamkowe = "))
print
Lc = int(math.floor(L))
Lu = L - Lc
s = ""
while Lc:
c = Lc % p
s = chr(c + 48) + s
Lc //= p
if s == "": s = "0"
s = s + ","
while m:
Lu *= p
c = int(math.floor(Lu))
s += chr(c + 48)
Lu -= c
m -= 1
print "%f(10) = %s(%d)" % (L, s, p)
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">
Przeliczanie stałoprzecinkowej liczby dziesiętnej<br>
na zapis w systemie pozycyjnym o podstawie 2...10
</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">Liczba =</td>
<td>
<input value=
"32.7125" name="inp_l" size="20" style="text-align: right">
</td>
</tr>
<tr>
<td align=
"right">Podstawa (2...10) =</td>
<td>
<input value=
"8" name="inp_p" size="20" style="text-align: right">
</td>
</tr>
<tr>
<td align=
"right">Ilość cyfr po przecinku =</td>
<td>
<input type=
"text" name="inp_m" size="20" value="10" style="text-align: right">
</td>
</tr>
</table>
</div>
<p style=
"TEXT-ALIGN: center">
<input onclick=
"main();" type="button" value="Przelicz" name="B1">
</p>
<p id=
"out_t" style="TEXT-ALIGN: center">...</p>
</form>

<script language=javascript>


// Przeliczanie dziesiętnej liczby stałoprzecinkowej
// na zapis w systemie pozycyjnym o podstawie 2...10
//--------------------------------------------------
// (C)2005 mgr Jerzy Wałaszek
// I Liceum Ogólnokształcące
// im. K. Brodzińskiego
// w Tarnowie
//--------------------------------------------------

function main()
{
var s,t,L,Lu,p,c,Lc,m;

L = parseFloat(document.frmprzelicz.inp_l.value);
p = parseInt(document.frmprzelicz.inp_p.value);
m = parseInt(document.frmprzelicz.inp_m.value);
if(isNaN(L) || isNaN(p) || isNaN(m))
t = "<font color=Red><b>Złe dane</b></font>";
else
{
Lc = Math.floor(L); Lu = L - Lc;
s = "";
do
{
c = Lc % p;
s = String.fromCharCode(c + 48) + s;
Lc = Math.floor(Lc / p);
} while(Lc);
s += ",";
while(m)
{
Lu *= p;
c = Math.floor(Lu);
s += String.fromCharCode(c + 48);
Lu -= c;
m--;
};
t = L + "<sub>(10)</sub> = " + s + "<sub>(" + p + ")</sub>";
};
document.getElementById("out_t").innerHTML = t;
}

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

bbf21fd7e131a60be40759b1d531480b.gif

Podany algorytm jest niejednorodny. Czy można go przekształcić tak, aby cała liczba stałoprzecinkowa była wyznaczana w jednym przebiegu bez podziału na część całkowitą i ułamkową? Czy potrafisz ocenić wady takiego rozwiązania?

 

 

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

 

Źródło: mgr Jerzy Wałaszek