/* * [TestRoman.java] * * Summary: convert Roman Numerals to long. * * Copyright: (c) 2009-2017 Roedy Green, Canadian Mind Products, http://mindprod.com * * Licence: This software may be copied and used freely for any purpose but military. * http://mindprod.com/contact/nonmil.html * * Requires: JDK 1.8+ * * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/ * * Version History: * 1.0 2007-08-17 */ package com.mindprod.example; import static java.lang.System.*; /** * convert Roman Numerals to long. * * @author Roedy Green, Canadian Mind Products * @version 1.0 2007-08-17 * @since 2007-08-17 */ public final class TestRoman { /** * extended roman numeral digits we allow */ private static final String VALID_NUMERALS = "IVXLCDMvxlcdm?!"; /** * values for unit test */ private static final String[] TESTS = { "MMVII", "MCMXCIX", "xv", "CIXMCMX" }; /** * corresponding value of roman numeral digit */ private static final long[] CORRESPONDING_VALUES = { /* I */ 1, /* V */ 5, /* X */ 10, /* L */ 50, /* C */ 100, /* D */ 500, /* M */ 1000, /* v */ 5000, /* x */ 10000, /* l */ 50000, /* c */ 100000, /* d */ 500000L, /* m */ 1000000L, /* ? */ 5000000L, /* ? */ 10000000L }; /** * Test harness for romanToLong * * @param args not used */ public static void main( String[] args ) { for ( String test : TESTS ) { out.println( test + " : " + romanToLong( test ) ); } // prints: // MMVII > 2007 // MCMXCIX > 1999 // xv > 15000 // CIXMCMX > 2001 } /** * converts a Roman Numeral String to a long. Based on Pascal algorithm posted at * http://www.merlyn.demon.co.uk/programs/cvt_rome.pas Also accepts fake Roman numbers to extend the range: vxlcdm?! * v=5000 ... !=10,000,000 This code also accepts numbers that are malformed, in that the numerals are out of order * e.g. "CIXMCMX" * * @param romanNumerals string of roman numerals to convert. No spaces or commas. * * @return long equivalent. */ @SuppressWarnings( { "WeakerAccess" } ) public static long romanToLong( final String romanNumerals ) { long sum = 0; long oldV = 0; // process the string right to left for ( int k = romanNumerals.length() - 1; k >= 0; k-- ) { final char c = romanNumerals.charAt( k ); final int pos = VALID_NUMERALS.indexOf( c ); if ( pos < 0 ) { throw new IllegalArgumentException( "invalid Roman numeral " + c + " in " + romanNumerals ); } long newV = CORRESPONDING_VALUES[ pos ]; if ( newV < oldV ) { newV = -newV; } sum += newV; oldV = newV; } return sum; } }