All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hfg.math.RomanNumeralSymbol Maven / Gradle / Ivy

There is a newer version: 20240423
Show newest version
package com.hfg.math;

import java.util.Map;

import com.hfg.util.collection.OrderedMap;


//------------------------------------------------------------------------------
/**
 Individual Roman numeral symbol representation. Used by the RomanNumeral class,
 it encapsulates the logic of which symbols can precede a given symbol.
 

See http://en.wikipedia.org/wiki/Roman_numerals

@author J. Alex Taylor, hairyfatguy.com */ //------------------------------------------------------------------------------ // com.hfg XML/HTML Coding Library // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com // [email protected] //------------------------------------------------------------------------------ public class RomanNumeralSymbol implements Comparable { //************************************************************************** // PRIVATE FIELDS //************************************************************************** char mLetter; int mValue; private static Map sValueMap = new OrderedMap(10); //************************************************************************** // PUBLIC FIELDS //************************************************************************** /** The Roman numeral for the integer 1. */ public static RomanNumeralSymbol I = new RomanNumeralSymbol('I', 1); /** The Roman numeral for the integer 5. */ public static RomanNumeralSymbol V = new RomanNumeralSymbol('V', 5); /** The Roman numeral for the integer 10. */ public static RomanNumeralSymbol X = new RomanNumeralSymbol('X', 10); /** The Roman numeral for the integer 50. */ public static RomanNumeralSymbol L = new RomanNumeralSymbol('L', 50); /** The Roman numeral for the integer 100. */ public static RomanNumeralSymbol C = new RomanNumeralSymbol('C', 100); /** The Roman numeral for the integer 500. */ public static RomanNumeralSymbol D = new RomanNumeralSymbol('D', 500); /** The Roman numeral for the integer 1000. */ public static RomanNumeralSymbol M = new RomanNumeralSymbol('M', 1000); //************************************************************************** // CONSTRUCTORS //************************************************************************** //-------------------------------------------------------------------------- private RomanNumeralSymbol(char inLetter, int inValue) { mLetter = inLetter; mValue = inValue; sValueMap.put(mLetter, this); } //************************************************************************** // PUBLIC METHODS //************************************************************************** //-------------------------------------------------------------------------- /** Returns the RomanNumeralSymbol value for the specified character. */ public static RomanNumeralSymbol valueOf(char inLetter) { return sValueMap.get(Character.toUpperCase(inLetter)); } //-------------------------------------------------------------------------- /** Returns an array of all the RomanNumeralSymbol values. */ public static RomanNumeralSymbol[] values() { return sValueMap.values().toArray(new RomanNumeralSymbol[1]); } //-------------------------------------------------------------------------- /** Returns the character value of the Roman numeral symbol. */ public char getLetter() { return mLetter; } //-------------------------------------------------------------------------- /** Returns the integer value of the Roman numeral symbol. */ public int getIntValue() { return mValue; } //-------------------------------------------------------------------------- /** Returns the Roman numeral string value of the Roman numeral symbol. */ @Override public String toString() { return mLetter + ""; } //-------------------------------------------------------------------------- /** Numerically compares two RomanNumeralSymbol objects. */ public int compareTo(RomanNumeralSymbol inObj) { return NumUtil.compare(mValue, inObj.mValue); } //-------------------------------------------------------------------------- /** Returns whether this symbol can legally precede the specified symbol given the subtractive principle. */ /* From wikipedia: Subtractive principle Generally, Roman numerals are written in descending order from left to right, and are added sequentially, for example MMVI (2006) is interpreted as 1000 + 1000 + 5 + 1. Certain combinations employ a subtractive principle, which specifies that where a symbol of smaller value precedes a symbol of larger value, the smaller value is subtracted from the larger value, and the result is added to the total. For example, in MCMXLIV (1944), t he symbols C, X and I each precede a symbol of higher value, and the result is interpreted as 1000 plus (1000 minus 100) plus (50 minus 10) plus (5 minus 1). A numeral for 10n (I, X, or C) may not precede a numeral larger than 10n+1, where n is an integer. That is, I may precede V and X, but not L or C; X may precede L or C, but not D or M. The numerals 5?10n (V, L, or D) may not be followed by a numeral of greater or equal value. Any symbol that appears more than once consecutively may not be followed by a symbol of larger value. */ public boolean canPrecede(RomanNumeralSymbol inSymbol) { boolean result; if (inSymbol.getIntValue() < getIntValue()) { result = true; } else { double predecessorLog10 = Math.log10((double)getIntValue()); result = (predecessorLog10%1 == 0 && (inSymbol.getIntValue() <= Math.pow(10, (predecessorLog10 + 1)))); } return result; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy