Convertire un numero in un numero romano in javaScript

Come posso convertire numeri interi in numeri romani ?

function romanNumeralGenerator (int) { } 

Ad esempio, vedere i seguenti esempi di input e output:

 1 = "I" 5 = "V" 10 = "X" 20 = "XX" 3999 = "MMMCMXCIX" 

Avvertenza: supportano solo numeri compresi tra 1 e 3999

    C’è una bella qui su questo blog che ho trovato usando google:

    http://blog.stevenlevithan.com/archives/javascript-roman-numeral-converter

     function romanize (num) { if (!+num) return NaN; var digits = String(+num).split(""), key = ["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM", "","X","XX","XXX","XL","L","LX","LXX","LXXX","XC", "","I","II","III","IV","V","VI","VII","VIII","IX"], roman = "", i = 3; while (i--) roman = (key[+digits.pop() + (i * 10)] || "") + roman; return Array(+digits.join("") + 1).join("M") + roman; } 
     function romanize(num) { var lookup = {M:1000,CM:900,D:500,CD:400,C:100,XC:90,L:50,XL:40,X:10,IX:9,V:5,IV:4,I:1},roman = '',i; for ( i in lookup ) { while ( num >= lookup[i] ) { roman += i; num -= lookup[i]; } } return roman; } 

    Ripubblicato da un commento del 2008, all’indirizzo: http://blog.stevenlevithan.com/archives/javascript-roman-numeral-converter

    VISUALIZZA DEMO

    Non capisco perché la soluzione di Everyones sia così lunga e usi multipli per cicli.

     function convertToRoman(num) { var roman = {"M" :1000, "CM":900, "D":500, "CD":400, "C":100, "XC":90, "L":50, "XL":40, "X":10, "IX":9, "V":5, "IV":4, "I":1}; var str = ""; for (var i of Object.keys(roman) ) { var q = Math.floor(num / roman[i]); num -= q * roman[i]; str += i.repeat(q); } return str; } 

    Queste funzioni convertono qualsiasi numero intero positivo nella sua stringa di numero romano equivalente; e qualsiasi numero romano al suo numero.

    Numero al numero romano:

     Number.prototype.toRoman= function () { var num = Math.floor(this), val, s= '', i= 0, v = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1], r = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I']; function toBigRoman(n) { var ret = '', n1 = '', rem = n; while (rem > 1000) { var prefix = '', suffix = '', n = rem, s = '' + rem, magnitude = 1; while (n > 1000) { n /= 1000; magnitude *= 1000; prefix += '('; suffix += ')'; } n1 = Math.floor(n); rem = s - (n1 * magnitude); ret += prefix + n1.toRoman() + suffix; } return ret + rem.toRoman(); } if (this - num || num < 1) num = 0; if (num > 3999) return toBigRoman(num); while (num) { val = v[i]; while (num >= val) { num -= val; s += r[i]; } ++i; } return s; }; 

    Numero romano stringa al numero:

     Number.fromRoman = function (roman, accept) { var s = roman.toUpperCase().replace(/ +/g, ''), L = s.length, sum = 0, i = 0, next, val, R = { M: 1000, D: 500, C: 100, L: 50, X: 10, V: 5, I: 1 }; function fromBigRoman(rn) { var n = 0, x, n1, S, rx =/(\(*)([MDCLXVI]+)/g; while ((S = rx.exec(rn)) != null) { x = S[1].length; n1 = Number.fromRoman(S[2]) if (isNaN(n1)) return NaN; if (x) n1 *= Math.pow(1000, x); n += n1; } return n; } if (/^[MDCLXVI)(]+$/.test(s)) { if (s.indexOf('(') == 0) return fromBigRoman(s); while (i < L) { val = R[s.charAt(i++)]; next = R[s.charAt(i)] || 0; if (next - val > 0) val *= -1; sum += val; } if (accept || sum.toRoman() === s) return sum; } return NaN; }; 

    Di seguito ho sviluppato la soluzione ricorsiva. La funzione restituisce una lettera e quindi chiama se stessa per restituire la lettera successiva. Lo fa fino a quando il numero passato alla funzione è 0 che significa che tutte le lettere sono state trovate e possiamo uscire dalla ricorsione.

     var romanMatrix = [ [1000, 'M'], [900, 'CM'], [500, 'D'], [400, 'CD'], [100, 'C'], [90, 'XC'], [50, 'L'], [40, 'XL'], [10, 'X'], [9, 'IX'], [5, 'V'], [4, 'IV'], [1, 'I'] ]; function convertToRoman(num) { if (num === 0) { return ''; } for (var i = 0; i < romanMatrix.length; i++) { if (num >= romanMatrix[i][0]) { return romanMatrix[i][1] + convertToRoman(num - romanMatrix[i][0]); } } } 

    So che questa è una vecchia domanda, ma sono piuttosto orgoglioso di questa soluzione 🙂 Gestisce solo numeri inferiori a 1000, ma potrebbe essere facilmente ampliato per includere, per quanto grande, la necessità di aggiungere alla matrice 2D ‘numeralCodes’.

     var numeralCodes = [["","I","II","III","IV","V","VI","VII","VIII","IX"], // Ones ["","X","XX","XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"], // Tens ["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"]]; // Hundreds function convert(num) { var numeral = ""; var digits = num.toString().split('').reverse(); for (var i=0; i < digits.length; i++){ numeral = numeralCodes[i][parseInt(digits[i])] + numeral; } return numeral; } 
        

    JavaScript

     function romanize (num) { if (!+num) return false; var digits = String(+num).split(""), key = ["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM", "","X","XX","XXX","XL","L","LX","LXX","LXXX","XC", "","I","II","III","IV","V","VI","VII","VIII","IX"], roman = "", i = 3; while (i--) roman = (key[+digits.pop() + (i * 10)] || "") + roman; return Array(+digits.join("") + 1).join("M") + roman; } 

    molti altri suggerimenti possono essere trovati su http://blog.stevenlevithan.com/archives/javascript-roman-numeral-converter

    Questa funzione convertirà qualsiasi numero inferiore a 3.9999.999 in roman. Si noti che i numeri più grandi di 3999 si troveranno all’interno di un’etichetta con la text-decoration impostata su overline , questo aggiungerà la overline che è la rappresentazione corretta per x1000 quando il numero è maggiore di 3999.

    Quattro milioni (4.000.000) sarebbero IV con due overline quindi, sarebbe necessario utilizzare qualche trucco per rappresentarlo, magari un DIV con border-top o un’immagine di sfondo con quelle due linee di sovrapposizione … Ogni linea di contorno rappresenta x1000.

     function convert(num){ num = parseInt(num); if (num > 3999999) { alert('Number is too big!'); return false; } if (num < 1) { alert('Number is too small!'); return false; } var result = '', ref = ['M','CM','D','CD','C','XC','L','XL','X','IX','V','IV','I'], xis = [1000,900,500,400,100,90,50,40,10,9,5,4,1]; if (num <= 3999999 && num >= 4000) { num += ''; // need to convert to string for .substring() result = ''; num = num.substring(num.length-3); } for (x = 0; x < ref.length; x++){ while(num >= xis[x]){ result += ref[x]; num -= xis[x]; } } return result; } 

    Dopo aver testato alcune delle implementazioni in questo post, ne ho creato uno nuovo ottimizzato per eseguire più velocemente. L’esecuzione del tempo è veramente bassa rispetto alle altre, ma ovviamente il codice è più brutto :). Potrebbe essere ancora più veloce con un array indicizzato con tutte le possibilità. Nel caso in cui aiuti qualcuno.

     function concatNumLetters(letter, num) { var text = ""; for(var i=0; i= 1000) { var thousands = ~~(arabic / 1000); roman = concatNumLetters("M", thousands); arabic -= thousands * 1000; } if (arabic >= 900) { roman += "CM"; arabic -= 900; } if (arabic >= 500) { roman += "D"; arabic -= 500; } if (arabic >= 400) { roman += "CD"; arabic -= 400; } if (arabic >= 100) { var hundreds = ~~(arabic / 100); roman += concatNumLetters("C", hundreds); arabic -= hundreds * 100; } if (arabic >= 90) { roman += "XC"; arabic -= 90; } if (arabic >= 50) { roman += "L"; arabic -= 50; } if (arabic >= 40) { roman += "XL"; arabic -= 40; } if (arabic >= 10) { var dozens = ~~(arabic / 10); roman += concatNumLetters("X", dozens); arabic -= dozens * 10; } if (arabic >= 9) { roman += "IX"; arabic -= 9; } if (arabic >= 5) { roman += "V"; arabic -= 5; } if (arabic >= 4) { roman += "IV"; arabic -= 4; } if (arabic >= 1) { roman += concatNumLetters("I", arabic); } return roman; } 

    Ho creato due array gemelli uno con numeri arabi e l’altro con caratteri romani.

     function convert(num) { var result = ''; var rom = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I']; var ara = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]; 

    Se vuoi convertire un grande numero con più simboli, forse questo algo potrebbe aiutare.

    L’unica premessa per i simboli è che deve essere dispari e seguire la stessa regola (1, 5, 10, 50,100 …., 10 ^ (N) / 2, 10 ^ (N)).

     var rnumbers = ["I","V","X","L","C","D","M"]; rnumbers = rnumbers.concat(["V","X","L","C","D","M"].map(function(n) {return ''+n+' '})); rnumbers = rnumbers.concat(["V","X","L","C","D","M"].map(function(n) {return ''+n+' '})); rnumbers = rnumbers.concat(["V","X","L","C","D","M"].map(function(n) {return ''+n+' '})); String.prototype.repeat = function( num ) { return new Array( num + 1 ).join( this ); }; function toRoman(n) { if(!n) return ""; var strn = new String(n); var strnlength = strn.length; var ret = ""; for(var i = 0 ; i < strnlength; i++) { var index = strnlength*2 -2 - i*2; var str; var m = +strn[i]; if(index > rnumbers.length -1) { str = rnumbers[rnumbers.length-1].repeat(m*Math.pow(10,Math.ceil((index-rnumbers.length)/2))); }else { str = rnumbers[index].repeat(m); if (rnumbers.length >= index + 2) { var rnregexp = rnumbers[index] .split("(").join('\\(') .split(")").join('\\)'); str = str.replace(new RegExp('(' + rnregexp + '){9}'), rnumbers[index] + rnumbers[index + 2]) .replace(new RegExp('(' + rnregexp + '){5}'), rnumbers[index + 1]) .replace(new RegExp('(' + rnregexp + '){4}'), rnumbers[index] + rnumbers[index + 1]) } } ret +=str; } return ret; } 
      

     function convertToRoman(num) { var romans = { 1000: 'M', 900: 'CM', 500: 'D', 400: 'CD', 100: 'C', 90: 'XC', 50: 'L', 40: 'XL', 10: 'X', 9: 'IX', 5: 'V', 4: 'IV', 1: 'I' }; var popped, rem, roman = '', keys = Object.keys(romans); while (num > 0) { popped = keys.pop(); m = Math.floor(num / popped); num = num % popped; console.log('popped:', popped, ' m:', m, ' num:', num, ' roman:', roman); while (m-- > 0) { roman += romans[popped]; } while (num / popped === 0) { popped = keys.pop(); delete romans[popped]; } } return roman; } var result = convertToRoman(3999); console.log(result); document.getElementById('roman').innerHTML = 'Roman: ' + result; 
     p { color: darkblue; } 
     

    Decimal: 3999

    Roman:

    L’ho appena fatto su freecodecamp. Può essere facilmente ampliato.

     function convertToRoman(num) { var roman =""; var values = [1000,900,500,400,100,90,50,40,10,9,5,4,1]; var literals = ["M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"]; for(i=0;i=values[i]){ if(5< =num && num<=8) num -= 5; else if(1<=num && num<=3) num -= 1; else num -= values[i]; roman += literals[i]; i--; } } return roman; } 

    Personalmente ritengo che il modo più accurato (non affatto il più veloce) sia con la ricorsione.

     function convert(num) { if(num < 1){ return "";} if(num >= 40){ return "XL" + convert(num - 40);} if(num >= 10){ return "X" + convert(num - 10);} if(num >= 9){ return "IX" + convert(num - 9);} if(num >= 5){ return "V" + convert(num - 5);} if(num >= 4){ return "IV" + convert(num - 4);} if(num >= 1){ return "I" + convert(num - 1);} } console.log(convert(39)); //Output: XXXIX 

    Questo supporterà solo i numeri 1-40 , ma può essere facilmente esteso seguendo lo schema.

     /*my beginner-nooby solution for numbers 1-999 :)*/ function convert(num) { var RomNumDig = [['','I','II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'],['X','XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'], ['C','CC','CCC','CD','D','DC','DCC','DCCC','CM']]; var lastDig = num%10; var ourNumb1 = RomNumDig[0][lastDig]||''; if(num>=10) { var decNum = (num - lastDig)/10; if(decNum>9)decNum%=10; var ourNumb2 = RomNumDig[1][decNum-1]||'';} if(num>=100) { var hundNum = ((num-num%100)/100); var ourNumb3 = RomNumDig[2][hundNum-1]||'';} return ourNumb3+ourNumb2+ourNumb1; } console.log(convert(950));//CML /*2nd my beginner-nooby solution for numbers 1-10, but it can be easy transformsd for larger numbers :)*/ function convert(num) { var ourNumb = ''; var romNumDig = ['I','IV','V','IX','X']; var decNum = [1,4,5,9,10]; for (var i=decNum.length-1; i>0; i--) { while(num>=decNum[i]) { ourNumb += romNumDig[i]; num -= decNum[i]; } } return ourNumb; } console.log(convert(9));//IX 
     function toRoman(n) { var decimals = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]; var roman = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I']; for (var i = 0; i < decimals.length; i++) { if(n < 1) return ""; if(n >= decimals[i]) { return roman[i] + toRoman(n - decimals[i]); } } } 

    Questa funzione funziona sui diversi set di caratteri in ogni cifra. Per aggiungere un’altra cifra aggiungi la stringa del numero romano il 1 posto, 5 posto e il prossimo 1 posto. Questo è bello perché lo aggiorni solo conoscendo il prossimo set di caratteri usato.

     function toRoman(n){ var d=0,o="",v,k="IVXLCDM".split(""); while(n!=0){ v=n%10,x=k[d],y=k[d+1],z=k[d+2]; o=["",x,x+x,x+x+x,x+y,y,y+x,y+x+x,y+x+x+x,x+z][v]+o; n=(nv)/10,d+=2; } return o } var out = ""; for (var i = 0; i < 100; i++) { out += toRoman(i) + "\n"; } document.getElementById("output").innerHTML = out; 
     
    
    

    SE questo numero in HTMLElement (come span), ti consigliamo di aggiungere il formato dei data-format attributi HTML :

     

    Phase 4 Sales

    Nota: questo non è uno standard HTML. Il codice Javascript utilizzato è visibile quando scorri verso il basso nella sezione html su jsfiddle.

    DEMO

    Questo funziona per tutti i numeri che hanno bisogno solo dei numeri romani M e inferiori.

     function convert(num) { var code = [ [1000, "M"], [900, "CM"], [800, "DCCC"], [700, "DCC"], [600, "DC"], [500, "D"], [400, "CD"], [300, "CCC"], [200, "CC"], [100, "C"], [90, "XC"], [80, "LXXX"], [70, "LXX"], [60, "LX"], [50, "L"], [40, "XL"], [30, "XXX"], [20, "XX"], [10, "X"], [9, "IX"], [8, "VIII"], [7, "VII"], [6, "VI"], [5, "V"], [4, "IV"], [3, "III"], [2, "II"], [1, "I"], ]; var rom = ""; for(var i=0; i= code[i][0]) { rom += code[i][1]; num -= code[i][0]; } } return rom; } 

    Questa è la prima volta che mi sono bloccato su Freecodecamp. Ho esaminato alcune soluzioni qui e sono rimasto sorpreso da quanto fossero diversi. Ecco cosa ha finito per funzionare per me.

     function convertToRoman(num) { var roman = ""; var lookupObj = { 1000:"M", 900:"CM", 500:"D", 400:"CD", 100:"C", 90:"XC", 50:"L", 40:"XL", 10:"X", 9:"IX", 4:"IV", 5:"V", 1:"I", }; var arrayLen = Object.keys(lookupObj).length; while(num>0){ for (i=arrayLen-1 ; i>=0 ; i--){ if(num >= Object.keys(lookupObj)[i]){ roman = roman + lookupObj[Object.keys(lookupObj)[i]]; num = num - Object.keys(lookupObj)[i]; break; } } } return roman; } convertToRoman(1231); 
     function convertToRoman(num) { var romNumerals = [["M", 1000], ["CM", 900], ["D", 500], ["CD", 400], ["C", 100], ["XC", 90], ["L", 50], ["XL", 40], ["X", 10], ["IX", 9], ["V", 5], ["IV", 4], ["I", 1]]; var runningTotal = 0; var roman = ""; for (var i = 0; i < romNumerals.length; i++) { while (runningTotal + romNumerals[i][1] <= num) { runningTotal += romNumerals[i][1]; roman += romNumerals[i][0]; } } return roman; } 
     function convertToRoman(num) { var roNumerals = { M: Math.floor(num / 1000), CM: Math.floor(num % 1000 / 900), D: Math.floor(num % 1000 % 900 / 500), CD: Math.floor(num % 1000 % 900 % 500 / 400), C: Math.floor(num % 1000 % 900 % 500 % 400 / 100), XC: Math.floor(num % 1000 % 900 % 500 % 400 % 100 / 90), L: Math.floor(num % 1000 % 900 % 500 % 400 % 100 % 90 / 50), XL: Math.floor(num % 1000 % 900 % 500 % 400 % 100 % 90 % 50 / 40), X: Math.floor(num % 1000 % 900 % 500 % 400 % 100 % 90 % 50 % 40 / 10), IX: Math.floor(num % 1000 % 900 % 500 % 400 % 100 % 90 % 50 % 40 % 10 / 9), V: Math.floor(num % 1000 % 900 % 500 % 400 % 100 % 90 % 50 % 40 % 10 % 9 / 5), IV: Math.floor(num % 1000 % 900 % 500 % 400 % 100 % 90 % 50 % 40 % 10 % 9 % 5 / 4), I: Math.floor(num % 1000 % 900 % 500 % 400 % 100 % 90 % 50 % 40 % 10 % 9 % 5 % 4 / 1) }; var roNuStr = ""; for (var prop in roNumerals) { for (i = 0; i < roNumerals[prop]; i++) { roNuStr += prop; } } return roNuStr; } convertToRoman(9); 
     function convertToRoman (num) { var v = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]; var r = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I']; var s = ""; for(i = 0; i < v.length; i++) { value = parseInt(num/v[i]); for(j = 0; j < value; j++) { s += r[i]; } num = num%v[i]; } return s; } 

    Ancora fiero di farlo 🙂 Funziona tra 1-3999.

     var converterArray = [{"1":["I","IV","V","IX"], "2":["X","XL","L","XC"], "3":["C","CD","D","CM"], "4":["M"]} ]; function convertToRoman(num) { var romanNumeral = []; var numArr = num.toString().split(''); var numLength = numArr.length; for (var i = 0; i 

    La mia soluzione suddivide il numero in una serie di stringhe, aggiunge zeri a ciascun elemento in base alla sua posizione relativa alla lunghezza della matrice, converte le nuove stringhe con zeri in numeri romani e quindi li unisce nuovamente. Funzionerà solo con numeri fino a 3999:

     function convertToRoman(num){ var rnumerals = { 1 : 'I', 2 : 'II', 3 : 'III', 4 : 'IV', 5 : 'V', 6 : 'VI', 7 : 'VII', 8 : 'VIII', 9 : 'IX', 10 : 'X', 20 : 'XX', 30 : 'XXX', 40 : 'XL', 50 : 'L', 60 : 'LX', 70 : 'LXX', 80 : 'LXXX', 90 : 'XC', 100 : 'C', 200 : 'CC', 300 : 'CCC', 400 : 'CD', 500 : 'D', 600 : 'DC', 700 : 'DCC', 800 : 'DCCC', 900 : 'CM', 1000: 'M', 2000: 'MM', 3000: 'MMM'}; var zeros, romNum; var arr = num.toString().split(""); var romArr = []; for(var i=0; i < arr.length; i++){ zeros = "0".repeat((arr.length - i - 1)); arr[i] = arr[i].concat(zeros); romArr.push(rnumerals[(arr[i])]); } romNum = romArr.join(''); return romNum; } 

    Se è solo a scopo di visualizzazione, usa l’HTML standard con un po ‘di JS per il valore (se necessario) e il CSS per renderlo in linea:

     ol.roman-lowercase, ol.roman-uppercase { display: inline-flex; margin: 0; padding: 0; } ol.roman-lowercase { list-style: lower-roman inside; } ol.roman-uppercase { list-style: upper-roman inside; } 
     
     function convertToRoman(num) { var arr = []; for (var i = 0; i < num.toString().length; i++) { arr.push(Number(num.toString().substr(i, 1))); } var romanArr = [ ["I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"], ["X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"], ["C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"], ["M"] ]; var roman = arr.reverse().map(function (val, i) { if (val === 0) { return ""; } if (i === 3) { var r = ""; for (var j = 0; j < val; j++) { r += romanArr[i][0]; } return r; } else { return romanArr[i][val - 1]; } }); console.log(roman.reverse().join("")); return roman.join(""); } convertToRoman(10); 

    Ecco una soluzione di espressione regolare:

     function deromanize(roman) { var r = 0; // regular expressions to check if valid Roman Number. if (!/^M*(?:D?C{0,3}|C[MD])(?:L?X{0,3}|X[CL])(?:V?I{0,3}|I[XV])$/.test(roman)) throw new Error('Invalid Roman Numeral.'); roman.replace(/[MDLV]|C[MD]?|X[CL]?|I[XV]?/g, function(i) { r += {M:1000, CM:900, D:500, CD:400, C:100, XC:90, L:50, XL:40, X:10, IX:9, V:5, IV:4, I:1}[i]; }); return r; } 
     var romanNumerals = [ ['M', 1000],['CM', 900],['D', 500],['CD', 400],['C', 100],['XC', 90],['L', 50],['XL', 40],['X', 10],['IX', 9],['V', 5],['IV', 4],['I', 1]]; RomanNumerals = { romerate: function(foo) { var bar = ''; romanNumerals.forEach(function(buzz) { while (foo >= buzz[1]) { bar += buzz[0]; foo -= buzz[1]; } }); return bar; }, numerate: function(x) { var y = 0; romanNumerals.forEach(function(z) { while (x.substr(0, z[0].length) == z[0]) { x = x.substr(z[0].length); y += z[1]; } }); return y; } }; 

    So che questa è una domanda datata ma ho la soluzione più corta di quelle elencate qui e ho pensato di condividere perché penso sia più facile da capire.

    Questa versione non richiede alcuna logica codificata per casi limite come 4 (IV), 9 (IX), 40 (XL), 900 (CM), ecc. Come fanno gli altri. Ciò significa anche che è in grado di gestire numeri più grandi superiori a 3999 in teoria supponendo che venga applicata la regola “non più di 3 di fila”.

    Ho provato questo contro 1-3999 e funziona perfettamente.

     function convertToRoman(num) { //create key:value pairs var romanLookup = {M:1000, D:500, C:100, L:50, X:10, V:5, I:1}; var roman = []; var romanKeys = Object.keys(romanLookup); var curValue; var index; var count = 1; for(var numeral in romanLookup){ curValue = romanLookup[numeral]; index = romanKeys.indexOf(numeral); while(num >= curValue){ if(count < 4){ //push up to 3 of the same numeral roman.push(numeral); } else { //else we had to push four, so we need to convert the numerals //to the next highest denomination "coloring-up in poker speak" //Note: We need to check previous index because it might be part of the current number. //Example:(9) would attempt (VIIII) so we would need to remove the V as well as the I's //otherwise removing just the last three III would be incorrect, because the swap //would give us (VIX) instead of the correct answer (IX) if(roman.indexOf(romanKeys[index - 1]) > -1){ //remove the previous numeral we worked with //and everything after it since we will replace them roman.splice(roman.indexOf(romanKeys[index - 1])); //push the current numeral and the one that appeared two iterations ago; //think (IX) where we skip (V) roman.push(romanKeys[index], romanKeys[index - 2]); } else { //else Example:(4) would attemt (IIII) so remove three I's and replace with a V //to get the correct answer of (IV) //remove the last 3 numerals which are all the same roman.splice(-3); //push the current numeral and the one that appeared right before it; think (IV) roman.push(romanKeys[index], romanKeys[index - 1]); } } //reduce our number by the value we already converted to a numeral num -= curValue; count++; } count = 1; } return roman.join(""); } convertToRoman(36);