Strona główna » Algorytmy » Artykuły » Ułamek z liczby dziesiętnej
 

Ułamek z liczby dziesiętnej

· część 1 · część 2 ·

Wstęp

W poprzedniej części została utworzona klasa ulamek, która umożliwia pracę na ułamkach w trakcie wykonywania programu bez błędu przybliżenia. Klasa choć funkcjonalna wciąż można rozszerzać dodając nowe funkcjonalności.

Idea

Pierwsze rozszerzenie biblioteki będzie dotyczyć rozszerzenia funkcjonalności o wczytywanie ułamka z zapisu dziesiętnego. Przykładowo ułamek będzie można utworzyć wpisując tylko 3,72. Problem ten można rozwiązać mnożąc licznik przez m aż nie będzie części ułamkowej. Później wystarczy ustalić mianownik na m i zredukować ułamek, aby uzyskać najprostszy zapis wczytanej liczby przy pomocy ułamka.

Implementacja

Wczytywanie ułamka z liczby dziesiętnej będzie możliwe podczas tworzenia zmiennej, dlatego zostanie dodany nowy konstruktor, który przyjmował jako argument liczbę rzeczywistą x. Na jej podstawie zostanie utworzony ułamek, który będzie reprezentował x.

C++
C#
  1.   public ulamek(double x) {
  2.     int mn = 1;
  3.     while (x * mn - Math.Floor(x * mn) != 0)
  4.       mn *= 10;
  5.     licznik = (int)(x * mn);
  6.     mianownik = mn;
  7.     redukuj();
  8.   }

(2.) Na początek istniej przypuszczenie, że liczba nie ma części dziesiętnej, dlatego zmienna mn przyjmuje wartość 1. (3.) Następnie w pętli jest sprawdzane czy po pomnożeniu liczby x przez mn istnieje jakaś część dziesiętna. Jeśli istnieje to (4.) należy pomnożyć mnożnik mn przez 10. Po zakończeniu pętli (5.) odpowiednio zostaje ustalony licznik oraz (6.) mianownik. (7.) Zapisana liczba może jednak zostać zredukowana do prostszej postaci, dlatego wywołana zostaje funkcja redukuj().

Następnie rozpoczyna się sekcja prywatna klasy. Jest to część hermetyzacji klasy. Ma to za zadanie ograniczyć co może wywołać programista na tej klasie. Pozostawienie niektórych z tych funkcji publicznych mogłoby doprowadzić do nieoczekiwanego przerwania działania programu (poprzez nieprawidłową operację). W prywatnej części są zadeklarowane dwie zmienne typu int, które odpowiadają licznikowi i mianownikowi ułamka.

Przypisanie

Posiadając tego typu konstruktor łatwo przypuścić, że programista w trakcie pisania programu chciałby uniknąć wywoływania konstruktora i użyć tylko operatora przypisania =. Z tego powodu zostanie dodany nowy operator.

W języku C# nie można nadpisać operatora =, ale można dokonać konwersji niejawnej z typu double na ulamek. Dzięki temu program przypisując wartość typu double będzie wiedział, aby użyć nowego konstruktora, a nie np. napisanego w poprzedniej części, który akceptował tylko liczby całkowite.

C++
C#
  1.   public static implicit operator ulamek(double d) {
  2.     return new ulamek(d);
  3.   }

Wypisywanie ułamka

Do tej pory użycie operatora << wypisywało ułamek w najprostszej możliwej postaci - w formie ułamka niewłaściwego. Jednak taka metoda nie zawsze jest przejrzysta. Tym razem cel polega na poprawieniu funkcji tak, aby wypisywała ułamek w formie mieszanej. Wypisywanie w takiej formie pozwoli uniknąć wypisywania np. 12/1.

C++
C#
  1.   public override string ToString() {
  2.     string s = "";
  3.     if ((int)(this.licznik / this.mianownik) != 0)
  4.       s = String.Format("{0} ", (int)(this.licznik / this.mianownik));
  5.     if (this.licznik % this.mianownik != 0)
  6.       s += String.Format("{0}/{1} ", this.licznik % this.mianownik, this.mianownik);
  7.     return s;
  8.   }

(2.) Przygotuj zmienną, aby dopisywać kolejne części ułamka. Następnie (3.) sprawdź czy istnieje część całkowita. Jeśli tak to (4.) dopisz ją do wyniku s. Podobnie sprawdź (5.) czy pozostała część ułamkowa istnieje. Jeśli tak (6.) to też ją dopisz. Na koniec (6.) zwróć wartość przechowywaną w s.

Testowanie funkcji

Deklaracja i przypisanie wartości

Przypisanie wartości zmiennej przechowujące ułamki można zapisać na dwa sposoby. Pierwszy z nich korzysta z operatora przypisania, a drugi z konstruktora. Oba są w pełni poprawne.

C++
C#
  1.     ulamek c1 = 3.72;
  2.     ulamek c2 = new ulamek(3.72);

Wypisanie wyników

W celu przetestowania nowej metody wypisywania wystarczy wpisać:

C++
C#
  1.     Console.WriteLine(c1);