package com.mindprod.inwords;
/**
* Display a number in Roman numerals.
* <p/>
* e.g.
* 12345 -> " MMMMMMMMMMMMCCCXLV"
* <p/>
* You can think of Roman numerals as a sort of base 5 representation.
* It likely originated from counting on the fingers, where V represents one handful of fingers.
* The Mayans counted similarly with a dot for one and a horizontal bar for five.
*
* @author Roedy Green, Canadian Mind Products
* @version 1.2 1999-08-11 correct code for 8 to VIII not VII.
* thanks to bug report from "Oliver
* Borchert" <oliver.borchert@nist.gov>
* Why is this code written in an unusual way? see inwords.use
* There are terser algorithms, such as the Pascal version posted at
* http://www.merlyn.demon.co.uk/programs/cvt_rome.pas
* but they don't show the parallelism with other numbering systems
* and I think they are harder to understand.
* @since 1999-01-19
*/
public final class Roman implements ToWords
{
private static final int FIRST_COPYRIGHT_YEAR = 1999;
/**
* undisplayed copyright notice
*
* @noinspection UnusedDeclaration
*/
private static final String EMBEDDED_COPYRIGHT =
"Copyright: (c) 1999-2017 Roedy Green, Canadian Mind Products, http://mindprod.com";
private static final char[] fiveLetter = { 'V', 'L', 'D' };
private static final char[] unitLetter = { 'I', 'X', 'C', 'M' };
private static final int[] divisor = {
10, 10, 10, 1000000 };
/**
* test harness
*
* @param args not used
*/
public static void main( String[] args )
{
Test.test( new Roman() );
}
/**
* convert long integer into Roman Numerals. e.g. -12345 -> "minus MMMMMMMMMMMMCCCXLV" Handles negative and positive
* integers on range -Long.MAX_VALUE .. Long.MAX_VALUE; It cannot handle Long.MIN_VALUE;
*
* @param num number to convert to words
*
* @return words
*/
@SuppressWarnings( { "WeakerAccess" } )
public String toWords( long num )
{
if ( num < 0 )
{
return "The Romans had no negative numbers.";
}
if ( num == 0 )
{
return "The Romans had no zero.";
}
if ( num > 100000 )
{
return "too unwieldy for Roman numerals";
}
String s = "";
for ( int group = 0; num > 0; group++ )
{
int remdr = ( int ) ( num % divisor[ group ] );
num = num / divisor[ group ];
StringBuilder t;
if ( group == 3 )
{
t = new StringBuilder( remdr );
for ( int j = 0; j < remdr; j++ )
{
t.append( unitLetter[ group ] );
}
}
else
{
t = new StringBuilder( 3 );
switch ( remdr )
{
case 0:
break;
case 1:
t.append( unitLetter[ group ] );
break;
case 2:
t.append( unitLetter[ group ] );
t.append( unitLetter[ group ] );
break;
case 3:
t.append( unitLetter[ group ] );
t.append( unitLetter[ group ] );
t.append( unitLetter[ group ] );
break;
case 4:
t.append( unitLetter[ group ] );
t.append( fiveLetter[ group ] );
break;
case 5:
t.append( fiveLetter[ group ] );
break;
case 6:
t.append( fiveLetter[ group ] );
t.append( unitLetter[ group ] );
break;
case 7:
t.append( fiveLetter[ group ] );
t.append( unitLetter[ group ] );
t.append( unitLetter[ group ] );
break;
case 8:
t.append( fiveLetter[ group ] );
t.append( unitLetter[ group ] );
t.append( unitLetter[ group ] );
t.append( unitLetter[ group ] );
break;
case 9:
t.append( unitLetter[ group ] );
t.append( unitLetter[ group + 1 ] );
break;
}
}
s = t + s;
}
return s;
}
}