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.
Autor:Kuba Jarosz
Źródło:http://kodatnik.blogspot.com/
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




(6 głosów, średnia: 3,33 / 5)













