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.
// wykorzystujemy klasę Scanner z pakietu java.util
import java.util.*;

/**
 * Zamiana liczb zapisanych w systemie rzymskim i arabskim
 * @author kodatnik.blogspot.com
 */
public class RzymskieArabskie {

 // tablica liczb rzymskich (podstawowe + dozwolone)
 private static String[] rzymskie = {"M", "CM", "D", "CD", "C","XC", "L", "XL", "X", "IX", "V", "IV", "I"};
 // tablica odpowiadających im liczb arabskich
 private static int[] arabskie   = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};

 // metoda sprawdza czy podana liczba rzymska jest poprawna
 public static boolean czyPoprawnaRzymska(String liczba) {
  
  // konwertujemy liczbę na duże znaki (takie mamy w tablicy)
  liczba = liczba.toUpperCase();  
  
  // jeśli liczba jest pusta zwracamy fałsz
  if (liczba.length() == 0) return false;
  // jeśli wartość tego co dostajemy od użytkownika z tym co 
  // sami obliczymy (zamiana na arabską i ponowna na rzymską) jest różna zwracamy fałsz 
  if (!liczba.equals(naRzymska(naArabska(liczba)))) return false;
  // w każdym innym przypadku zwracamy prawdę
  return true;
 }

 // metoda sprawdza czy podana liczba arabska jest poprawna
 public static boolean czyPoprawnaArabska(int liczba) {
  // sprawdzamy zakres
  if (liczba < 1 || liczba > 3999) return false;  
  // jeśli w porządku zwracamy prawdę
  else return true;
 }
 
 // metoda zamienia liczbę arabską na rzymską
 public static String naRzymska(int liczba) {
 
  // zmienna wyjście będzie zawierała liczbę rzymską
  String wyjscie = "";
  
  // sprawdzamy w pętli naszą liczbę z poszczególnymi
  // elementami tablicy liczb arabskich
  for (int i = 0; i < arabskie.length; i++) {
   // dopóki liczba jest większa
   while (liczba >= arabskie[i]) {
    // tworzymy liczbę rzymską dodając odpowiedną wartość z tablicy rzymskie
    wyjscie += rzymskie[i];
    // zmniejszamy liczbę arabską o odpowiednią wartość
    liczba -= arabskie[i];
   }
  }
  // zwracamy liczbę rzymską (łańcuch tekstowy)
  return wyjscie;
}
 
 // meoda zamienia liczbę rzymską na arabską
 public static int naArabska(String liczba) {
  
  // konwertujemy liczbę na duże znaki (takie mamy w tablicy)
  liczba = liczba.toUpperCase();
      
  // zmienna wyjście będzie zawierała liczbę arabską
  int wyjscie = 0;
 
  // zmienna index umożliwi nam przemieszczanie się po liczbie rzymskiej
  int index = 0;      
      
  // sprawdzamy w pętli naszą liczbę z poszczególnymi
  // elementami tablicy liczb rzymskich
  for (int i = 0; i < rzymskie.length; i++) {
   // dopóki liczba zaczyna się z odpowiednią liczbą rzymską
   while (liczba.startsWith(rzymskie[i], index)) {
    // tworzymy liczbę arabską dodając odpowiedną wartość z tablicy arabskie
    wyjscie += arabskie[i];
    // przechodzimy do następnej pozycji w liczbie rzymskiej
    index += rzymskie[i].length();
   }
  }  
  // zwracamy liczbę arabską 
  return wyjscie;
 } 
  
   
 public static void main (String[] args) {
     
  Scanner wejscie = new Scanner(System.in);
     
  System.out.print ("Podaj liczbę z zakresu (1-3999) w systemie rzymskim: ");
     
  // pobieramy od użytkownika łańcuch tekstowy (liczbę rzymską)
  String rzymska = wejscie.nextLine();
     
  // sprawdzamy poprawność i wyświetlamy wynik konwersji lub komunikat o błędzie
  if(czyPoprawnaRzymska(rzymska)) {
   System.out.println ("Liczba zapisana w systemie arabskim: " + naArabska(rzymska));
  } else {
   System.out.println ("Niepoprawna liczba.");      
  }
     
  System.out.print ("Podaj liczbę z zakresu (1-3999) w systemie arabskim: ");
  
  // pobieramy od użytkownika liczbę (liczbę arabska)     
  int arabska = wejscie.nextInt();
     
  // sprawdzamy poprawność i wyświetlamy wynik konwersji lub komunikat o błędzie     
  if(czyPoprawnaArabska(arabska)) {
   System.out.println ("Liczba zapisana w systemie rzymskim: " + naRzymska(arabska));
  } else {
   System.out.println ("Niepoprawna liczba.");
  }
 }
}
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


4 Komentarze - 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 ^$^

Prześlij komentarz

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

Popularne posty