Zamiana liczb rzymskich na arabskie i na odwrót

Konwersja między różnymi formatami zapisu liczb zawsze jest dobrą wprawką programistyczną. Przyjrzyjmy się dwóm systemom zapisu. System arabski wykorzystuje cyfry od 0 do 9 i jest stosowany powszechnie na całym świecie. System rzymski opiera się na 7 znakach literowych (I - 1, V - 5, X - 10, L - 50, C - 100, D - 500, M - 1000). Poszczególne wartości są tworzone za pomocą odpowiednich zestawień znaków. Np. MCMXCIV odpowiada liczbie 1994. W jaki sposób prawidłowo odczytać wartość, znaki jednakowe są dodawane (np. XX - 10+10 = 20), znaki mniejsze stojące przed większymi są od nich odejmowane (np. IV - 5-1 = 4), znaki mniejsze stojące za większymi są do nich dodawane (np. VI - 5+1 = 6).

Dodatkowo jest kilka założeń, które powinny być przestrzegane:
  • nie można znaku stanowiącego jednostki (I), dziesiątki(X) lub setki(C) (nie dotyczy to znaku tysięcy - M) użyć więcej niż trzy razy, np. IIII jest niedozwolone,
  • znaki, które nie są symbolami jednostek (I), dziesiątek(X), setek (C), tysięcy (M) mogą występować tylko pojedynczo, np. LL jest niedozwolone,
  • znaki które można odejmować od znaków większych to tylko I, X, C, ale tylko jeśli znak większy nie jest więcej niż 10 razy większy, np. IC jest niedozwolone.
Zasady wyglądają strasznie ;) Poniżej algorytm, który dokona zamiany podanej przez użytkownika liczby w systemie rzymskim na system arabski i odwrotnie. W dwóch tablicach zapisane zostały podstawowe wartości w systemie rzymskim (7 podstawowych znaków plus dla uproszczenia algorytmu kilka wyjątków) oraz odpowiadające im wartości systemu arabskiego. Dodatkowo program sprawdza poprawność podawanych liczb. Dla systemu arabskiego jest sprawdzany zakres liczby (tylko liczby od 1 do 3999), a dla rzymskiego jej poprawność. Dla pominięcia wszelkich zawiłości związanych ze sprawdzeniem czy dana liczba rzymska została poprawnie podana przez użytkownika, metoda czyPoprawnaRzymska() dokonuje zamiany podanej liczby rzymskiej na arabską, a później dla uzyskanego wyniku z powrotem na rzymską. Jeśli wynik zgadza się z tym który podał użytkownik, program uznaje zapis za poprawny.
001.// wykorzystujemy klasę Scanner z pakietu java.util
002.import java.util.*;
003. 
004./**
005. * Zamiana liczb zapisanych w systemie rzymskim i arabskim
006. * @author kodatnik.blogspot.com
007. */
008.public class RzymskieArabskie {
009. 
010. // tablica liczb rzymskich (podstawowe + dozwolone)
011. private static String[] rzymskie = {"M", "CM", "D", "CD", "C","XC", "L", "XL", "X", "IX", "V", "IV", "I"};
012. // tablica odpowiadających im liczb arabskich
013. private static int[] arabskie   = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
014. 
015. // metoda sprawdza czy podana liczba rzymska jest poprawna
016. public static boolean czyPoprawnaRzymska(String liczba) {
017.   
018.  // konwertujemy liczbę na duże znaki (takie mamy w tablicy)
019.  liczba = liczba.toUpperCase(); 
020.   
021.  // jeśli liczba jest pusta zwracamy fałsz
022.  if (liczba.length() == 0) return false;
023.  // jeśli wartość tego co dostajemy od użytkownika z tym co
024.  // sami obliczymy (zamiana na arabską i ponowna na rzymską) jest różna zwracamy fałsz
025.  if (!liczba.equals(naRzymska(naArabska(liczba)))) return false;
026.  // w każdym innym przypadku zwracamy prawdę
027.  return true;
028. }
029. 
030. // metoda sprawdza czy podana liczba arabska jest poprawna
031. public static boolean czyPoprawnaArabska(int liczba) {
032.  // sprawdzamy zakres
033.  if (liczba < 1 || liczba > 3999) return false
034.  // jeśli w porządku zwracamy prawdę
035.  else return true;
036. }
037.  
038. // metoda zamienia liczbę arabską na rzymską
039. public static String naRzymska(int liczba) {
040.  
041.  // zmienna wyjście będzie zawierała liczbę rzymską
042.  String wyjscie = "";
043.   
044.  // sprawdzamy w pętli naszą liczbę z poszczególnymi
045.  // elementami tablicy liczb arabskich
046.  for (int i = 0; i < arabskie.length; i++) {
047.   // dopóki liczba jest większa
048.   while (liczba >= arabskie[i]) {
049.    // tworzymy liczbę rzymską dodając odpowiedną wartość z tablicy rzymskie
050.    wyjscie += rzymskie[i];
051.    // zmniejszamy liczbę arabską o odpowiednią wartość
052.    liczba -= arabskie[i];
053.   }
054.  }
055.  // zwracamy liczbę rzymską (łańcuch tekstowy)
056.  return wyjscie;
057.}
058.  
059. // meoda zamienia liczbę rzymską na arabską
060. public static int naArabska(String liczba) {
061.   
062.  // konwertujemy liczbę na duże znaki (takie mamy w tablicy)
063.  liczba = liczba.toUpperCase();
064.       
065.  // zmienna wyjście będzie zawierała liczbę arabską
066.  int wyjscie = 0;
067.  
068.  // zmienna index umożliwi nam przemieszczanie się po liczbie rzymskiej
069.  int index = 0;     
070.       
071.  // sprawdzamy w pętli naszą liczbę z poszczególnymi
072.  // elementami tablicy liczb rzymskich
073.  for (int i = 0; i < rzymskie.length; i++) {
074.   // dopóki liczba zaczyna się z odpowiednią liczbą rzymską
075.   while (liczba.startsWith(rzymskie[i], index)) {
076.    // tworzymy liczbę arabską dodając odpowiedną wartość z tablicy arabskie
077.    wyjscie += arabskie[i];
078.    // przechodzimy do następnej pozycji w liczbie rzymskiej
079.    index += rzymskie[i].length();
080.   }
081.  
082.  // zwracamy liczbę arabską
083.  return wyjscie;
084. }
085.   
086.    
087. public static void main (String[] args) {
088.      
089.  Scanner wejscie = new Scanner(System.in);
090.      
091.  System.out.print ("Podaj liczbę z zakresu (1-3999) w systemie rzymskim: ");
092.      
093.  // pobieramy od użytkownika łańcuch tekstowy (liczbę rzymską)
094.  String rzymska = wejscie.nextLine();
095.      
096.  // sprawdzamy poprawność i wyświetlamy wynik konwersji lub komunikat o błędzie
097.  if(czyPoprawnaRzymska(rzymska)) {
098.   System.out.println ("Liczba zapisana w systemie arabskim: " + naArabska(rzymska));
099.  } else {
100.   System.out.println ("Niepoprawna liczba.");     
101.  }
102.      
103.  System.out.print ("Podaj liczbę z zakresu (1-3999) w systemie arabskim: ");
104.   
105.  // pobieramy od użytkownika liczbę (liczbę arabska)    
106.  int arabska = wejscie.nextInt();
107.      
108.  // sprawdzamy poprawność i wyświetlamy wynik konwersji lub komunikat o błędzie    
109.  if(czyPoprawnaArabska(arabska)) {
110.   System.out.println ("Liczba zapisana w systemie rzymskim: " + naRzymska(arabska));
111.  } else {
112.   System.out.println ("Niepoprawna liczba.");
113.  }
114. }
115.}
Przykłady uruchomień aplikacji:
Podaj liczbę z zakresu (1-3999) w systemie rzymskim: MCMXCIV
Liczba zapisana w systemie arabskim: 1994
Podaj liczbę z zakresu (1-3999) w systemie arabskim: 666
Liczba zapisana w systemie rzymskim: DCLXVI
Podaj liczbę z zakresu (1-3999) w systemie rzymskim: ICVI
Niepoprawna liczba.
Podaj liczbę z zakresu (1-3999) w systemie arabskim: 978
Liczba zapisana w systemie rzymskim: CMLXXVIII


5 Komentarzy - Zamiana liczb rzymskich na arabskie i na odwrót

Anonimowy pisze...

19997

Devon pisze...

@Anonimowy: Tak nie do końca wiem o co Ci chodzi :) Algorytm tak jak w opisie działa dla liczb mniejszych od 4000.

Anonimowy pisze...

czy mógłby ktoś umieścić jeszcze schemat blokowy do podanych algorytmów, byłabym bardzo wdzięczna.Jestem zupełnym laikiem a muszę to wykonać za pomocą graficzną...z góry dziękuję za pomoc

Anonimowy pisze...

Może by ktoś dodał jakieś zadania do rozwiązania, bo jutro mam poprawę kartkówki i chcę wiedzieć czy umiem czy nie :(
^$^ NiELeGaLnA ^$^

obiady domowe pisze...

dobre podczas pisania pracy

Prześlij komentarz

Możesz użyć niektórych tagów HTML, takich jak <b>, <i>, <u>, <a> Nie spamuj :)

Popularne posty