Java – Wprowadzenie Do Liczb Rzymskich

Tekst (opis) ten pochodzi z wikipedi.pl – implementacja w Javie już nie. Dokończenie mojego posta

"Java – Zadania Testowe " z Marca 2008

Najprawdopodobniej spotkaliśmy się już gdzieś z liczbami rzymskimi. Można je spotkać w starszych filmach oglądanych w telewizji (np. "Copyright MCMXLVI" zamiast "-Copyright 1946") lub na ścianach bibliotek, czy uniwersytetów (napisy typu "założone w MDCCCLXXXVIII" zamiast "założone w 1888 roku"). Mogliśmy je także zobaczyć na przykład w referencjach bibliograficznych. Ten system reprezentowania liczb sięga czasów starożytnego Rzymu

W liczbach rzymskich wykorzystuje się siedem znaków, które na różne sposoby się powtarza i łączy, aby zapisać pewną liczbę:

  • I = 1
  • V = 5
  • X = 10
  • L = 50
  • C = 100
  • D = 500
  • M = 1000

Poniżej znajdują się podstawowe zasady konstruowania liczb rzymskich:

  • Znaki są addytywne. I to 1, II to 2, a III to 3. VI to 6 (dosłownie, „5 i 1”), VII to 7, a VIII to 8.
  • Znaki dziesiątek (I, X, C i M) mogą się powtarzać do trzech razy. Za czwartym należy odjąć od następnego większego znaku piątek. Nie można zapisać liczby 4 jako IIII. Zamiast tego napiszemy IV ("o 1 mniej niż 5"). Liczba 40 zapisujemy jako XL (o 10 mniej niż 50), 41 jako XLI, 42 jako XLII, 43 jako XLIII, a potem 44 jako XLIV (o 10 mniej niż 50, a potem o 1 mniej niż 5).
  • Podobnie w przypadku 9. Musimy odejmować od wyższego znaku dziesiątek: 8 to VIII, lecz 9 zapiszemy jako IX (o 1 mniej niż 10), a nie jako VIIII (ponieważ znak nie może się powtarzać cztery razy). Liczba 90 to XC, a 900 zapiszemy jako CM.
  • Znaki piątek nie mogą się powtarzać. Liczba 10 jest zawsze reprezentowana przez X, nigdy przez VV. Liczba 100 to zawsze C, nigdy LL.
  • Liczby rzymskie są zawsze pisane od najwyższych do najniższych i czytane od lewej do prawej, więc porządek znaków jest bardzo ważny. DC to 600, jednak CD jest kompletnie inną liczbą (400, ponieważ o 100 mniej niż 500). CI to 101, jednak IC nie jest żadną poprawną liczbą rzymską (nie możemy bezpośrednio odejmować 1 od 100, musimy to zapisać jako XCIX, o 10 mniej niż 100, dodać 1 mniej niż 10).{mospagebreak}

Zasady tworzenia liczb rzymskich prowadzą do kilku interesujących obserwacji:

  1. Istnieje tylko jeden poprawny sposób reprezentowania pewnej liczby w postaci rzymskiej.
  2. Odwrotność też jest prawdą: jeśli ciąg znaków jest poprawną liczbą rzymską, to reprezentuje ona tylko jedną liczbę (tzn. możemy ją przeczytać tylko w jeden sposób).
  3. Tylko ograniczony zakres liczb może być zapisany jako liczby rzymskie, a dokładniej liczby od 1 do 3999 (Liczby rzymskiej posiadają kilka sposobów wyrażania większych liczb np. poprzez dodanie nadkreślenia nad cyframi rzymskimi, co oznacza, że normalną wartość tej liczby trzeba pomnożyć przez 1000, jednak nie będziemy się wdawać w szczegóły. Dla potrzeb tego rozdziału, założymy, że liczby rzymskie idą od 1 do 3999).
  4. Nie mamy możliwość zapisania 0 jako liczby rzymskiej. (Co ciekawe, starożytni Rzymianie nie wyobrażali sobie 0 jako liczby. Za pomocą liczb liczymy, ile czegoś mamy, jednak jak możemy policzyć coś, czego nie mamy?)
  5. Nie możemy w postaci liczby rzymskiej zapisać liczby ujemnej.
  6. W postaci liczby rzymskiej nie możemy zapisywać ułamków, czy liczb, które nie są całkowite.

Biorąc to wszystko pod uwagę, co możemy oczekiwać od zbioru funkcji, które konwertują z i na liczby rzymskie? Wymagania RomanNumeral.java

  1. RomanNumeral.java powinien zwracać rzymską reprezentację wszystkich liczb całkowitych z zakresu od 1 do 3999.
  2. RomanNumeral.java powinien nie zadziałać (ang. fail ), gdy otrzyma liczbę całkowitą z poza przedziału od 1 do 3999.
  3. RomanNumeral.java powinien nie zadziałać, gdy otrzyma niecałkowitą liczbę.
  4. RomanNumeral.java powinien zawsze zwrócić liczbę rzymską korzystając z wielkich liter lub małych liter.

/*******************************************************************************************************
* @(#)RomanNumeral.java
*
* RomanNumeral application
*
* @author Andre W
* @version 1.00 2008
*******************************************************************************************************/
public class RomanNumeral
{
private String _value;
private int _intValue;

public RomanNumeral(int number)
{
_intValue = number;
_value = evaluate(_intValue);
}

public int getIntValue()
{
return _intValue;
}

public String toString()
{
return this._value;
}

public String getValue()
{
return this._value;
}

public String getLowerCaseValue()
{
return this._value.toLowerCase();
}

public static String evaluate(int value)
{
StringBuffer ret = new StringBuffer();

value = doThousands(value, ret);
value = doHundreds(value, ret);
value = doTens(value, ret);
doOnes(value, ret);

return ret.toString();
}

private static int doThousands(int value, StringBuffer buff)
{
int ret = value;
int subtract = 0;

while (value >= 900)
{
if(value >= 1000)
{
buff.append("M");
subtract += 1000;
value -= 1000;
}
else if(value >= 900)
{
buff.append("CM");
subtract += 900;
value -= 900;
}
}

return ret – subtract;
}

private static int doHundreds(int value, StringBuffer buff)
{
int ret = value;
int subtract = 0;

while (value >= 90)
{
if(value >= 500)
{
buff.append("D");
subtract += 500;
value -= 500;
}
else if(value >= 400)
{
buff.append("CD");
subtract += 400;
value -= 400;
}
else if(value >= 100)
{
buff.append("C");
subtract += 100;
value -= 100;
}
else if(value >= 90)
{
buff.append("XC");
subtract += 90;
value -= 90;
}
}

return ret – subtract;
}

private static int doTens(int value, StringBuffer buff)
{
int ret = value;
int subtract = 0;

while (value >= 9)
{
if(value >= 50)
{
buff.append("L");
subtract += 50;
value -= 50;
}
if(value >= 40)
{
buff.append("XL");
subtract += 40;
value -= 40;
}
else if(value >= 10)
{
buff.append("X");
subtract += 10;
value -= 10;
}
else if(value == 9)
{
buff.append("IX");
subtract += 9;
value -= 9;
}
}

return ret – subtract;
}

private static void doOnes(int value, StringBuffer buff)
{
while (value > 0)
{
if(value >= 5)
{
buff.append("V");
value -= 5;
}
else if(value == 4)
{
buff.append("IV");
value -= 4;
}
else if(value < 4) { buff.append("I"); value -= 1; } } } public static void main(String[] args) { for(int x = 1; x <= 3999; x++) { RomanNumeral rn = new RomanNumeral(x); System.out.println("Int value: " + rn.getIntValue() + " = " + rn.toString() + " or " + rn.getLowerCaseValue()); } } } [/sourcecode]

Skomentuj

Please log in using one of these methods to post your comment:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Log Out / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Log Out / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s

%d bloggers like this: