Integer to Roman Numerals

Michaelmontero
9 min readApr 30, 2023

--

Roman numerals are a numerical system that originated in ancient Rome and were used throughout the Roman Empire. They use a combination of letters to represent numbers, with the basic symbols being I, V, X, L, C, D, and M.

In this article/tutorial we will be converting integers to Roman numerals, but why bother to do that when you can just type in the number in a google search? Or better yet just use regular numbers like a normal person, so why bother. Well for those trying to get a better grasp of writing algorithms this will be a very useful exercise. It’s not just me that thinks so, both code wars and Leet code also believes it to be a great test on one’s ability to write algorithms so lets get to it just like the ancient Romans.

reject modernity embrace tradition

Okay so before we write the code, there are a few basic rules to writing out roman numerals, They use 7 letters to represent different numbers. These are I, V, X, L, C, D, and M which represent the numbers 1, 5, 10, 50, 100, 500, and 1000 respectively.

https://www.cuemath.com/numbers/roman-numerals/

Okay so there are actually more than a few rules, i will list them out from the same site above.

  • Rule 1: When certain numerals are repeated, the number represented by them is their sum. For example, II = 1 + 1 = 2, or XX = 10 + 10 = 20, or, XXX = 10 + 10 + 10 = 30.
  • Rule 2: It is to be noted that no Roman numerals can come together more than 3 times. For example, we cannot write 40 as XXXX
  • Rule 3: The letters V, L, and D are not repeated.
  • Rule 4: Only I, X, and C can be used as subtractive numerals. There can be 6 combinations when we subtract. These are IV = 5–1 = 4; IX = 10–1 = 9; XL = 50–10 = 40; XC = 100–10 = 90; CD = 500–100 = 400; and CM = 1000–100 = 900
  • Rule 5: When a Roman numeral is placed after another Roman numeral of greater value, the result is the sum of the numerals. For example, VIII = 5 + 1 + 1 + 1 = 8, or, XV = 10 + 5 = 15,
  • Rule 6: When a Roman numeral is placed before another Roman numeral of greater value, the result is the difference between the numerals. For example, IV = 5–1 = 4, or, XL = 50–10 = 40, or XC = 100–10 = 90
  • Rule 7: When a Roman numeral of a smaller value is placed between two numerals of greater value, it is subtracted from the numeral on its right. For example, XIV = 10 + (5–1) = 14, or, XIX = 10 + (10–1) = 19
  • Rule 8: To multiply a number by a factor of 1000 a bar is placed over it.
  • Rule 9: Roman numerals do not follow any place value system.
  • Rule 10: There is no Roman numeral for zero (0).

Okay now that you know the basic rules lets go ahead and finally write some code!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

let numberInput = 3489;
function returnRoman(num) {
const alphaRange = ['I', 'V', 'X', 'L', 'C', 'D', 'M'];
let ThousandInteg = Math.floor(num / 1000);
let hundredsInteg = Math.floor(num % 1000 /100);
let twoDigitInt = Math.floor(num % 100 / 10);
let singleDigit = Math.floor(num % 10);

console.log(ThousandInteg) // output: 3
console.log(hundredsInteg) // output: 4
console.log(twoDigitInt) // output: 8
console.log(singleDigit) // output: 9

Okay so something to know before we start is that this will work for a limit of 3999, being that is the same limitation for both code wars and leet code and most importantly if you have noticed from the chart that numbers 4,000 and above use a a letter that is outside the traditional 26 character keyboard we a both using. Also, the final code will be revealed at the end, it wont actually have all of the console logs.

Now that we have established that lets take a look at the code above, I declared and array with the 7 alphanumeric characters used in roman numerals. The number input in this example is 3489, the variables declared below the alphaRange array all use The Math.floor() function, whichJavaScript returns the largest integer less than or equal to a given number. In this case the given number is numberInput which has the value of num in our returnRoman function. We know our limit is 3999 so a total of 4 digits, to find the first digit representing the thousands value it is simply: the input number / 1000. Math.floor() is needed else the ThousandInteg variable will equal 3.489.

Next we have the value defining the hundreds, as you can see we use % for the modulus operator, which gives the remainder of the division of the first operand by the second operand. The operation num % 1000 /100 is basically dividing by 100 to what ever is left after dividing num by 1000 and rounding it with Math.floor(). A similar math operation is done to get the two digit integers. That is divide by 10 whatever is left after you divide num by 100. Then finally to get the final single digits representing 1–9 you round whatever is left after dividing num by 10.

let numberInput = 3489;

function returnRoman(num) {
const alphaRange = ['I', 'V', 'X', 'L', 'C', 'D', 'M'];
let ThousandInteg = num / 1000;
let hundredsInteg = Math.floor(num % 1000 /100);
let twoDigitInt = Math.floor(num % 100 / 10);
let singleDigit = Math.floor(num % 10);


//Thousands 1000
if (ThousandInteg <= 3) {
ThousandInteg = alphaRange[6].repeat(ThousandInteg);
}
//Hundreds 100
if (hundredsInteg <= 3 && hundredsInteg < 4) {
hundredsInteg = alphaRange[4].repeat(hundredsInteg);
} else if (hundredsInteg === 4) {
hundredsInteg = alphaRange[4] + alphaRange[5];
}
else if (hundredsInteg === 5) {
hundredsInteg = alphaRange[5];
}
else if (hundredsInteg <= 6 || hundredsInteg < 9) {
let modHundredsInteg = hundredsInteg % 5
hundredsInteg = alphaRange[5] + alphaRange[4].repeat(modHundredsInteg)
}
if (hundredsInteg === 9) {
hundredsInteg = alphaRange[4] + alphaRange[6];
}

Now to actually convert the numbers to Roman numerals we to do some if statements, since we are working with a limit of 3999 we know that the number in the thousands digit will always be three or less, and based on the rules we know that 3’s and 2’s and just repetitions of 1’s. In this case we utilize and if statement so that when the thousandth digit is 3 or less, we repeat the letter M, because M represent the thousandth digit for Roman numerals below 4,000. We use the .repeat() method to reassign the value to a repeated value in the array.

Now getting to evaluate the hundreds is a little trickier. This time we need the number representing the hundreds to be a repeat as long as it is three or less, however if it is equal to 4 we need it to be equal to CD or if it is equal to 5 then it is equal to D, but if it turns out to be a value that is less than or equal to 6 or less than 9 then we to return a value of D plus a repetition of C by whatever is left if you divide hundredsInteg by 5. Finally, if the hundredsInteg is equal to nine, then you return CM.

let numberInput = 3489;

function returnRoman(num) {
const alphaRange = ['I', 'V', 'X', 'L', 'C', 'D', 'M'];
let ThousandInteg = num / 1000;
let hundredsInteg = Math.floor(num % 1000 /100);
let twoDigitInt = Math.floor(num % 100 / 10);
let singleDigit = Math.floor(num % 10);


//Thousands 1000
if (ThousandInteg <= 3) {
ThousandInteg = alphaRange[6].repeat(ThousandInteg);
}
//Hundrends 100
if (hundredsInteg <= 3 && hundredsInteg < 4) {
hundredsInteg = alphaRange[4].repeat(hundredsInteg);
} else if (hundredsInteg === 4) {
hundredsInteg = alphaRange[4] + alphaRange[5];
}
else if (hundredsInteg === 5) {
hundredsInteg = alphaRange[5];
}
else if (hundredsInteg <= 6 || hundredsInteg < 9) {
let modHundredsInteg = hundredsInteg % 5
hundredsInteg = alphaRange[5] + alphaRange[4].repeat(modHundredsInteg)
}
if (hundredsInteg === 9) {
hundredsInteg = alphaRange[4] + alphaRange[6];
}
//tens 10
if (twoDigitInt <= 3 && twoDigitInt < 4) {
twoDigitInt = alphaRange[2].repeat(twoDigitInt);
} else if (twoDigitInt === 4){
twoDigitInt = alphaRange[2] + alphaRange[3];
} else if (twoDigitInt === 5) {
twoDigitInt = alphaRange[3];
}
else if (twoDigitInt <= 6 || twoDigitInt < 9) {
let modTwoDigitInt = twoDigitInt % 5
twoDigitInt = alphaRange[3] + alphaRange[2].repeat(modTwoDigitInt)
}
else if (twoDigitInt === 9) {
twoDigitInt = alphaRange[2] + alphaRange[4];
}
//single digits 1
if (singleDigit <= 3) {
singleDigit = alphaRange[0].repeat(singleDigit)
} else if (singleDigit === 4) {
singleDigit =alphaRange[0] + alphaRange[1];
} else if (singleDigit === 5) {
singleDigit = alphaRange[1]
} else if (singleDigit <= 6 || singleDigit < 9) {
let modSingleDigit = singleDigit % 5
singleDigit = alphaRange[1] + alphaRange[0].repeat(modSingleDigit)
} else if (singleDigit === 9) {
singleDigit = alphaRange[0] + alphaRange[2];
}

Okay so the same process applies to the numbers in the 10’s and single digits. For the 10’s, under three is a repeat of X’s, but four is represented as XL while five is simply L. The values between 6 and 9 for the double digits are L plus a repetition of X’s by whatever you get from dividing twoDigit variable by 5. Lastly with a value of 9 in the 10’s digit, it will return XC.

Finally for the single digits, as the vast majority of people know, values from one to three in Roman numerals is a repetition of I, while 4 is represented as IV and 5 as simply V. The single digit values of 6 through 9 is V plus a repetition of I by whatever is the result of dividing the single digit value by 5. Lastly a single digit value of 9 is IX.

//let numberInput = 3489;
//let numberInput = 2849;
//let numberInput = 1492;
//let numberInput = 1888;
//let numberInput = 1984;
let numberInput = 1993;

function returnRoman(num) {
const alphaRange = ['I', 'V', 'X', 'L', 'C', 'D', 'M'];
let ThousandInteg = num / 1000;
let hundredsInteg = Math.floor(num % 1000 /100);
let twoDigitInt = Math.floor(num % 100 / 10);
let singleDigit = Math.floor(num % 10);


//Kilos 1000
if (ThousandInteg <= 3) {
ThousandInteg = alphaRange[6].repeat(ThousandInteg);
}
//Benjamins 100
if (hundredsInteg <= 3 && hundredsInteg < 4) {
hundredsInteg = alphaRange[4].repeat(hundredsInteg);
} else if (hundredsInteg === 4) {
hundredsInteg = alphaRange[4] + alphaRange[5];
}
else if (hundredsInteg === 5) {
hundredsInteg = alphaRange[5];
}
else if (hundredsInteg <= 6 || hundredsInteg < 9) {
let modHundredsInteg = hundredsInteg % 5
hundredsInteg = alphaRange[5] + alphaRange[4].repeat(modHundredsInteg)
}
if (hundredsInteg === 9) {
hundredsInteg = alphaRange[4] + alphaRange[6];
}
//tens
if (twoDigitInt <= 3 && twoDigitInt < 4) {
twoDigitInt = alphaRange[2].repeat(twoDigitInt);
} else if (twoDigitInt === 4){
twoDigitInt = alphaRange[2] + alphaRange[3];
} else if (twoDigitInt === 5) {
twoDigitInt = alphaRange[3];
}
else if (twoDigitInt <= 6 || twoDigitInt < 9) {
let modTwoDigitInt = twoDigitInt % 5
twoDigitInt = alphaRange[3] + alphaRange[2].repeat(modTwoDigitInt)
}
else if (twoDigitInt === 9) {
twoDigitInt = alphaRange[2] + alphaRange[4];
}
//single digits
if (singleDigit <= 3) {
singleDigit = alphaRange[0].repeat(singleDigit)
} else if (singleDigit === 4) {
singleDigit =alphaRange[0] + alphaRange[1];
} else if (singleDigit === 5) {
singleDigit = alphaRange[1]
} else if (singleDigit <= 6 || singleDigit < 9) {
let modSingleDigit = singleDigit % 5
singleDigit = alphaRange[1] + alphaRange[0].repeat(modSingleDigit)
} else if (singleDigit === 9) {
singleDigit = alphaRange[0] + alphaRange[2];
}
return ThousandInteg + hundredsInteg + twoDigitInt + singleDigit;
}

console.log(returnRoman(numberInput))
//outPut: "MMMCDLXXXIX"
//outPut: "MMDCCCXLIX"
//outPut: "MCDXCII"
//outPut: "MDCCCLXXXVIII"
//outPut: "MCMLXXXIV"
//outPut: "MCMXCIII"

Now finally we make a return statement that concatenates the values from ThousandInteg, hundredsInteg, twoDigitInt and singleDigit.

You can take inspiration from this algorithm if and when you come across it in code wars or leet code, or you can pretend to be a person from ancient Rome and do what the Romans do while in Rome.

Be thankful that you are not actually living in acient rome

--

--