Converting decimal numbers to Roman numerals in JavaScript

Recently I decided to provide all the copyright dates on my sites in Roman numerals rather than decimal, just for something different. It’s not a major change I know, but it was something I wanted to do.

First of all I had to find out how the conversions were actually made. I went to Google, that all important source of information, and found an existing solution written in Java. I quickly converted this to JavaScript, and it is the current script running on the majority of my websites. This simple code is shown below:

``````var roman = new Array();
roman = ["M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"];
var decimal = new Array();
decimal = [1000,900,500,400,100,90,50,40,10,9,5,4,1];
function decimalToRomanSimple(value) {
if (value <= 0 || value >= 4000) return value;
var romanNumeral = "";
for (var i=0; i<roman.length; i++) {
while (value >= decimal[i]) {
value -= decimal[i];
romanNumeral += roman[i];
}
}
return romanNumeral;
}
``````

However, it is limited to numbers under 4000, which is fine for years, but what about numbers higher than this?

A quick look at the Wikipedia article on Roman numerals will reveal that numbers in thousands are usually written with a bar over the base numeral, or with rounded brackets placed around it. I prefer the bar method so this is what I am going to implement (as you will see however, changing it to use rounded brackets is very easy).

Both the `roman` and `decimal` arrays defined in the sample code above will be re-used. So assume that these have been defined as above. Next, I took the code within the `for` loop in the above sample and put it into its own function, with some additional information:

``````function getRoman(value) {
var romanNumeral = "";
var numThousands = 0;
for (var i=0; i<roman.length; i++) {
if (value == 0) break;
while (value >= decimal[i]) {
value -= decimal[i];
romanNumeral += roman[i];
if (roman[i] == 'M') numThousands++;
}
}
return { numThousands:numThousands, romanNumeral:romanNumeral };
}
``````

As you can see, it now also counts the “number of thousands” i.e. the number of times that an ‘M’ is inserted into the `romanNumeral` variable. This is then returned in an object with the generated Roman numeral.

I then created the `decimalToRoman()` function which uses the above function to generate the required numeral:

``````function decimalToRoman(value) {
// 3,888,888 is the longest number represented by Roman numerals
if (value <= 0 || value > 3888888) return value;
var romanNumeral1 = "";
var romanO = getRoman(value);
// If the number is 4000 or greater
if (romanO.numThousands > 4) {
var thousandString = "";
for (var j=0;j<romanO.numThousands;j++) thousandString += "M";
var thousandsO = getRoman(romanO.numThousands);
var thBase = "<span style='border-top:1px solid #000'>" +
thousandsO.romanNumeral + "</span>";
romanNumeral = romanO.romanNumeral.replace(thousandString, thBase);
}
else romanNumeral = romanO.romanNumeral;
return romanNumeral;
}
``````

This generates the Roman numeral and then checks to see if the number of thousands is 4 or more. If so, it then replaces the “thousand String” (a list of Ms) with the appropriate base number contained in a span with a CSS styled top border of 1px. This is where you can change the top border to use brackets if you so wish, by setting: `thBase = "(" + thousandsO.romanNumeral + ")";`.

I have created a Roman numeral test page where you can see it in action for yourself.

Any thoughts and comments, as always, greatly appreciated!