在 JavaScript 中将数字转换为罗马数字

如何将整数转换为 罗马数字

function romanNumeralGenerator (int) {


}

例如,请参阅下面的输入和输出示例:

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

注意: 只支持1到3999之间的数字

173121 次浏览

我在这个博客上用 google 找到了一个不错的例子:

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

function romanize (num) {
if (isNaN(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;
}

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;
}

许多其他建议可以在 http://blog.stevenlevithan.com/archives/javascript-roman-numeral-converter找到

这些函数将任意正整数转换为等效的罗马数字字符串,将任意罗马数字转换为它的数字。

数字到罗马数字:

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;
};

罗马数字字符串到数字:

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;
};

这个函数将把任何小于3,999,999的数字转换为 Roman。注意,大于3999的数字将出现在 text-decoration设置为 overline的标签中,这将添加 overline,当数字大于3999时,这将是 x1000的正确表示。

4百万(4,000,000)是两个 overline的静脉注射,所以,你需要使用一些技巧来表示,可能是一个 DIVborder-top,或者一些背景图像和这两个 overline... 每个 overline代表 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 = '<label style="text-decoration: overline;">'+convert(num.substring(0,num.length-3))+'</label>';
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;
}

如果这个数字在 HTMLElement中(如 span) ,我们建议添加 HTML 属性 data-format:

Number.prototype.toRoman = function() {
var e = Math.floor(this),
t, n = "",
i = 3999,
s = 0;
v = [1e3, 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"];
if (e < 1 || e > i) return "";
while (s < 13) {
t = v[s];
while (e >= t) {
e -= t;
n += r[s]
}
if (e == 0) return n;
++s
}
return ""
};
var fnrom = function(e) {
if (parseInt(e.innerHTML)) {
e.innerHTML = parseInt(e.innerHTML).toRoman()
}
};
setTimeout(function() {
[].forEach.call(document.querySelectorAll("[data-format=roman]"), fnrom)
}, 10)
Phase <span data-format="roman">4</span> Sales

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;
}
};

我个人认为最简洁的方法(绝不是最快的方法)是使用递归。

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

这将只支持数字 1-40,但是可以按照模式轻松地扩展它。

/*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 transformed 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 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];

然后我添加了一个扫描 roman 元素的循环,将仍然包含在 NUM 中的最大值添加到 Results T 中,然后我们减少相同数量的 NUM。

这就像我们用罗马数字映射 NUM 的一部分,然后减少它的相同数量。

  for (var x = 0; x < rom.length; x++) {
while (num >= ara[x]) {
result += rom[x];
num -= ara[x];
}
}
return result;
}

如果你想用更多的符号转换一个大数,也许这个算法可以帮助。

符号的唯一前提是必须是奇数且遵循相同的规则(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 '<span style="border-top:1px solid black; padding:1px;">'+n+'</span> '}));
rnumbers = rnumbers.concat(["V","X","L","C","D","M"].map(function(n) {return '<span style="border:1px solid black; border-bottom:1px none black; padding:1px;">'+n+'</span> '}));
rnumbers = rnumbers.concat(["V","X","L","C","D","M"].map(function(n) {return '<span style="border-top:3px double black; padding:1px;">'+n+'</span> '}));




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;
}

<input type="text" value="" onkeyup="document.getElementById('result').innerHTML = toRoman(this.value)"/>


<br/><br/>


<div id="result"></div>

我知道这是一个老问题,但我对这个解决方案感到非常自豪:)它只处理小于1000的数字,但可以很容易地扩展到包括任何大你需要添加到“ numalCodes”2D 数组。

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;
}
<input id="text-input" type="text">
<button id="convert-button" onClick="var n = parseInt(document.getElementById('text-input').value);document.getElementById('text-output').value = convert(n);">Convert!</button>
<input id="text-output" style="display:block" type="text">

此函数对每个数字中的不同字符集起作用。要添加另一个数字添加罗马数字字符串的1位,5位和下一个1位。这很好,因为您只需要知道下一组使用的字符就可以更新它。

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=(n-v)/10,d+=2;
}
  

return o
}


var out = "";


for (var i = 0; i < 100; i++) {
out += toRoman(i) + "\n";
}


document.getElementById("output").innerHTML = out;
<pre id="output"></pre>

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]);
}
}
}
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;
}

转载自2008年的评论,网址: http://blog.stevenlevithan.com/archives/javascript-roman-numeral-converter

视图演示

这适用于所有数字只需要罗马数字 M 和以下。

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.length; i++) {
while(num >= code[i][0]) {
rom += code[i][1];
num -= code[i][0];
}
}
return rom;
}

这是我第一次真正困在自由生态营地。我在这里仔细研究了一些解决方案,对它们的不同之处感到惊讶。这就是我最后的成果。

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 converter(numToConv) {
var numToRom = [];
var numToRome = "";
var R = [['M',1000], ['D',500], ['C',100], ['L',50], ['X',10], ['V',5], ['I',1]];
while (numToConv > 0) {
if (numToConv > R[0][1]) {
if (numToConv < R[0][1] * 5 - R[0][1]) {
numToRom.push([R[0][0],"next one goes aftah"]);
numToConv = Math.abs(numToConv - R[0][1]);
console.log("Next comes after: " + R[0][0] + " (" + R[0][1] + ")");
console.log(numToConv);
} else {
numToConv = 0;
break;
}
}
for (var i = 0; i < R.length; i++) {
if (R[i][1] == numToConv) {
numToRom.push([R[i][0],"end"]);
numToConv = Math.abs(numToConv - R[i][1]);
console.log("End: " + numToConv);
} else if (i > 0) {
if ((R[i-1][1] > numToConv) && (R[i][1] < numToConv)) {
console.log(numToConv + " is between: " + R[i][1]  + " (" + R[i][0] + ") and: " +  R[i - 1][1]  + " (" + R[i - 1][0] + ")");
var threshold = R[i - 1][1] - Math.pow(10, numToConv.toString().length - 1);
console.log("threshold: " + threshold + " : " + R[i][1] + " : " + Math.pow(10, numToConv.toString().length - 1));
if (numToConv  < threshold) {
numToRom.push([R[i][0],"next one goes aftah"]);
numToConv = Math.abs(numToConv - R[i][1]);
console.log("Next comes after: " + R[i][0] + " (" + R[i][1] + ")");
console.log(numToConv);
} else {
numToRom.push([R[i-1][0],"next one goes befoah"]);
numToConv = Math.abs(numToConv - threshold + Math.pow(10, numToConv.toString().length - 1));
console.log("Next comes before: " + R[i-1][0] + " (" + R[i-1][1] + ")");
console.log(numToConv);
}
}
}
}
}
console.log("numToRom: " + numToRom);
for (var i = 0; i < numToRom.length; i++) {
if (numToRom[i][1] == "next one goes befoah") {
numToRome += (numToRom[i+1][0] + numToRom[i][0]);
console.log("numToRome goes befoah: " + numToRome + " i: " + i);
i++;
} else {
numToRome += numToRom[i][0];
console.log("numToRome goes aftah: " + numToRome + " i: " + i);
}
}
console.log("numToRome: " + numToRome);
return numToRome;

}

带注释的编辑代码:

function converter(numToConv) {
var numToRom = []; //an array empty, ready to store information about the numbers we will use as we analyse the given number
var numToRome = ""; // this is a string to add the Roman letters forming our returning number
var R = [['M',1000], ['D',500], ['C',100], ['L',50], ['X',10], ['V',5], ['I',1]]; //this array stores the matches with the arabic numbers that we are going to need
while (numToConv > 0) { //just checking, there is no zero
if (numToConv > R[0][1]) { //checks if the number is bigger than the bigger number in the array
if (numToConv < R[0][1] * 5 - R[0][1]) { //checks if it is larger even than 4 times the larger number in the array (just because there is not usually a way to express a number by putting 4 times the same letter i.e there is no "IIII", or "XXXX" etc)
numToRom.push([R[0][0],"next one goes aftah"]);//here is the information we want to pass, we add the letter we are about to use along with info about the next letter
numToConv = Math.abs(numToConv - R[0][1]);// and now we are subtracting the value of the letter we are using from the number
console.log("Next comes after: " + R[0][0] + " (" + R[0][1] + ")");// informing about what we encountering
console.log(numToConv);//..as well as what's the next number
} else { //if the number is larger than 4 times the larger number in the array (thus it cannot be expressed)
numToConv = 0; //then 0 the number (unnecessary but still, no problem doing it)
break;//and of course, breaking the loop, no need to continue
}
}
for (var i = 0; i < R.length; i++) {//now we are about to search our number for each cell of the array with the roman letters (again and again)
if (R[i][1] == numToConv) { //if the number is equal to the one in the cell (that means the conversion is over)
numToRom.push([R[i][0],"end"]); //we pass the information about that cell along with the indication that the conversion has ended
numToConv = Math.abs(numToConv - R[i][1]);//thai can also be skipped but again there is o harm in keeping it
console.log("End: " + numToConv);// again informing about what we encountering
} else if (i > 0) { //just a precaution because we are about to use "i-1"
if ((R[i-1][1] > numToConv) && (R[i][1] < numToConv)) {//we find the range in which is the given number (for instance: the number 4 is between 1[I] and 5[V])
console.log(numToConv + " is between: " + R[i][1]  + " (" + R[i][0] + ") and: " +  R[i - 1][1]  + " (" + R[i - 1][0] + ")");// once again informing
var threshold = R[i - 1][1] - Math.pow(10, numToConv.toString().length - 1);// we create this "threshold" to check if the next number is going before or after this one (difference between 7[VII] and 9[IX]). it is the larger number of our range - 10^[depends on how large is the number we want to convert] (for 999, the threshold is 900, it is smaller 1000 - 10^2)
console.log("threshold: " + threshold + " : " + numToConv + " : " + R[i - 1][1] + " : " + R[i][1] + " : " + Math.pow(10, numToConv.toString().length - 1));
if (numToConv  < threshold) {//if the number is smaller than the "threshold" (like 199 where its threshold is 400)
numToRom.push([R[i][0],"next one goes aftah"]);//then the next number is going after
numToConv = Math.abs(numToConv - R[i][1]);//and again, subtract the used value of the number we are converting
console.log("Next comes after: " + R[i][0] + " (" + R[i][1] + ")");
console.log(numToConv);
} else { // now, if the number is larger than the threshold (like 99 where its threshold is 90)
numToRom.push([R[i-1][0],"next one goes befoah"]);// then the next number is going before the one we add now
numToConv = Math.abs(numToConv - R[i - 1][1]);// again, the subtraction, it was "threshold + Math.pow(10, numToConv.toString().length - 1)" but I changed it to "R[i - 1][1]", same result, less operations
console.log("Next comes before: " + R[i-1][0] + " (" + R[i-1][1] + ")");
console.log(numToConv);
}
}
}
}
}
console.log("numToRom: " + numToRom); //now that we have all the info we need about the number, show it to the log (just for a check)
for (var i = 0; i < numToRom.length; i++) {//..and we start running through that info to create our final number
if (numToRom[i][1] == "next one goes befoah") {//if our information about the cell tells us that the next letter is going before the current one
numToRome += (numToRom[i+1][0] + numToRom[i][0]);// we add both to our string (the next one first)
console.log("numToRome goes befoah: " + numToRome + " i: " + i);
i++;//and we add an extra '1' to the i, so it will skip the next letter (mind that there won't be more than one letters saying that the next one is going before them in a row
} else {//if the next one is going after the current one
numToRome += numToRom[i][0]; //we just add the one we are on to the string and go forth
console.log("numToRome goes aftah: " + numToRome + " i: " + i);
}
}
console.log("numToRome: " + numToRome);
return numToRome;//return the string and we are done
}

这个版本不像其他版本那样需要任何边缘情况(如 4(IV),9(IX),40(XL),900(CM), etc.)的硬编码逻辑。

我已经测试了从1-3999的数据集这个代码,它工作。

极低密度辐射;

这也意味着这个解决方案可以处理比最大罗马比例(3999)更大的数字。

似乎有一个交替的规则来决定下一个主要的罗马数字字符。首先乘以5得到下一个数字 V 然后乘以2得到 X 然后乘以5得到 L 再乘以2得到 C 等等得到下一个主要的数字字符。在这种情况下,让我们假设“ T”被添加到刻度中,以允许比原始罗马刻度允许的3999更大的数字。为了保持相同的算法“ T”将代表5000。

I = 1
V = I * 5
X = V * 2
L = X * 5
C = L * 2
D = C * 5
M = D * 2
T = M * 5

这样我们就可以表示从4000到5000的数字; 例如 MT = 4000。


密码:

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);

看来我不是唯一一个在 FreeCodeCamp 的挑战赛中卡住的人。但我还是想和你分享我的代码。它的性能相当好,几乎比排名第一的解决方案快了10% (我还没有测试所有其他的解决方案,我想我的解决方案不是最快的)。但我认为这很简单,也很容易理解:

function convertToRoman(num) {
// Some error checking first
if (+num > 9999) {
console.error('Error (fn convertToRoman(num)): Can\'t convert numbers greater than 9999. You provided: ' + num);
return false;
}
if (!+num) {
console.error('Error (fn convertToRoman(num)): \'num\' must be a number or number in a string. You provided: ' + num);
return false;
}


// Convert the number into
// an array of the numbers
var arr = String(+num).split('').map((el) => +el );


// Keys to the roman numbers
var keys = {
1: ['', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'],
2: ['', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'],
3: ['', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM'],
4: ['', 'M', 'MM', 'MMM', 'MMMM', 'MMMMM', 'MMMMMM', 'MMMMMMM', 'MMMMMMMM', 'MMMMMMMMM'],
};


// Variables to help building the roman string
var i = arr.length;
var roman = '';


// Iterate over each number in the array and
// build the string with the corresponding
// roman numeral
arr.forEach(function (el) {
roman += keys[i][el];
i--;
});


// Return the string
return roman;
}

它只能转换最多9999的数字,这似乎是一个限制。但事实是,从10000及以上的一行应提供上述文字。而我还没有解决。

希望这个能帮到你。

我已经开发了下面的递归解决方案。函数返回一个字母,然后调用自身返回下一个字母。直到传递给函数的数字是 0为止,这意味着所有的字母都已经找到,我们可以退出递归。

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]);
}
}
}

在测试了本文中的一些实现之后,我创建了一个新的优化的实现,以便更快地执行。与其他代码相比,执行时间确实很低,但是显然代码更难看:)。 如果有一个索引数组,它甚至可以更快,而且具有所有的可能性。 以防万一。

function concatNumLetters(letter, num) {
var text = "";
for(var i=0; i<num; i++){
text += letter;
}
return text;
}




function arabicToRomanNumber(arabic) {
arabic = parseInt(arabic);
var roman = "";
if (arabic >= 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;
}
function convertToRoman(num) {


var search = {
"0":["I","II","III","IV","V","VI","VII","VIII","IX"],
"1":["X","XX","XXX","XL","L","LX","LXX","LXXX","XC"],
"2":["C","CC","CCC","CD","D","DC","DCC","DCCC","CM"],
"3":["M","MM","MMM","MV^","V^","V^M","V^MM","V^MMM","MX^"],
};


var numArr = num.toString().split("").reverse();
var romanReturn = [];
for(var i=0; i<numArr.length; i++){
romanReturn.unshift(search[i][numArr[i]-1]);
}
return romanReturn.join("");
}

这就是我的解决方案,我不太确定效果如何。

function convertToRoman(num) {


var uni = ["","I","II","III","IV","V","VI","VII","VIII","IX"];
var dec = ["","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"];
var cen = ["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"];
var mil = ["","M","MM","MMM","MMMM","MMMMM","MMMMMM","MMMMMMM","MMMMMMMM","MMMMMMMMMM"];


var res =[];


if(num/1000 > 0)
{
res = res.concat(mil[Math.floor(num/1000)]);
}


if(num/100 > 0)
{
res = res.concat(cen[Math.floor((num%1000)/100)]);
}


if(num/10 >0)
{
res = res.concat(dec[Math.floor(((num%1000)%100)/10)]);
}


res=res.concat(uni[Math.floor(((num%1000)%100)%10)]);


return res.join('');
}

这是我的 “功能齐全”解决方案。

var numerals = ["I","V","X","L","C","D","M"],
number = 1453,
digits = Array(~~(Math.log10(number)+1)).fill(number).map((n,i) => Math.trunc(n%Math.pow(10,i+1)/Math.pow(10,i))),  // <- [3,5,4,1]
result = digits.reduce((p,c,i) => (c === 0 ? ""
: c < 4 ? numerals[2*i].repeat(c)
: c === 4 ? numerals[2*i] + numerals[2*i+1]
: c < 9 ? numerals[2*i+1] + numerals[2*i].repeat(c-5)
: numerals[2*i] + numerals[2*i+2]) + p,"");
console.log(result);

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;
}
<p>Decimal: 3999</p>
<p id="roman">Roman:</p>

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 toRoman(n) {
var r = '';
for (var c = 0; c < n.length; c++)
r += calcDigit(eval(n.charAt(c)), n.length - c - 1);
return r
}


function Level(i, v, x) {
this.i = i;
this.v = v;
this.x = x
}


levels = [];
levels[0] = new Level('I','V','X');
levels[1] = new Level('X','L','C');
levels[2] = new Level('C','D','M');


function calcDigit(d, l) {
if (l > 2) {
var str = '';
for (var m = 1; m <= d * Math.pow(10, l - 3); m++)
str += 'M';
return str
} else if (d == 1)
return levels[l].i;
else if (d == 2)
return levels[l].i + levels[l].i;
else if (d == 3)
return levels[l].i + levels[l].i + levels[l].i;
else if (d == 4)
return levels[l].i + levels[l].v;
else if (d == 5)
return levels[l].v;
else if (d == 6)
return levels[l].v + levels[l].i;
else if (d == 7)
return levels[l].v + levels[l].i + levels[l].i;
else if (d == 8)
return levels[l].v + levels[l].i + levels[l].i + levels[l].i;
else if (d == 9)
return levels[l].i + levels[l].x;
else
return ''
}
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;
}

这是我在免费营地做的,很容易扩展。

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.length;i++){
if(num>=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;
}

我讨厌在数组中列出每一种可能性(许多人选择这个数组来解决这个难题) ,所以我使用另一个函数来完成这项工作。我的解决办法是:

//a function that convert a single number to roman number, you can choose how to convert it so later you can apply to different part of the number
function romannum(num,rnum1,rnum2,rnum3){
var result = "";
if(num >= 1 && num < 4){
while(num>0){
result += rnum1;
num--;
}
}
else if(num > 5 && num < 9){
result = rnum2;
while(num>5){
result += rnum1;
num--;
}
}
else if(num == 4){
result += rnum1 + rnum2;
}
else if( num == 5){
result += rnum2;
}
else if( num == 9){
result += rnum1+ rnum3;
}
return result;
}
//the main function
function convertToRoman(num) {
num = num.toString().split('');
var length = num.length;
var x = 0;
var result =[];


while((length - x) > 0){
if(length -x === 4){
result.push(romannum(num[x],"M","",""));
}
else if(length -x  === 3){
result.push(romannum(num[x],"C","D","M"));
}
else if(length - x  === 2){
result.push(romannum(num[x],"X","L","C"));
}
else if(length - x === 1){
result.push(romannum(num[x],"I","V","X"));
}
x++;
}

我从头开始写这个免费生态营挑战赛。我希望这将帮助某人。

function convertToRoman(num) {


var nums = [0, 0, 0, 0];


var numsRom = ["", "", "", ""];


var nRom = {
I: "I",
V: "V",
X: "X",
L: "L",
C: "C",
D: "D",
M: "M"
};
/*
1,
5,
10,
50,
100,
500,
1000
*/


var i;


nums[0] = Math.floor(num / 1000);
nums[1] = Math.floor((num - nums[0] * 1000) / 100);
nums[2] = Math.floor((num - nums[0] * 1000 - nums[1] * 100) / 10);
nums[3] = num - nums[0] * 1000 - nums[1] * 100 - nums[2] * 10;


//1000
for (i = 0; i < nums[0]; i++) {
numsRom[0] += nRom.M;
}


//100
switch (nums[1]) {
case 1:
case 2:
case 3:
for (i = 0; i < nums[1]; i++) {
numsRom[1] += nRom.C;
}
break;
case 4:
numsRom[1] += nRom.C + nRom.D;
break;
case 5:
numsRom[1] += nRom.D;
break;
case 6:
case 7:
case 8:
numsRom[1] += nRom.D;
for (i = 0; i < nums[1] - 5; i++) {
numsRom[1] += nRom.C;
}
break;
case 9:
numsRom[1] += nRom.C + nRom.M;
}


//10
switch (nums[2]) {
case 1:
case 2:
case 3:
for (i = 0; i < nums[2]; i++) {
numsRom[2] += nRom.X;
}
break;
case 4:
numsRom[2] += nRom.X + nRom.L;
break;
case 5:
numsRom[2] += nRom.L;
break;
case 6:
case 7:
case 8:
numsRom[2] += nRom.L;
for (i = 0; i < nums[2] - 5; i++) {
numsRom[2] += nRom.X;
}
break;
case 9:
numsRom[2] += nRom.X + nRom.C;
}


//1
switch (nums[3]) {
case 1:
case 2:
case 3:
for (i = 0; i < nums[3]; i++) {
numsRom[3] += nRom.I;
}
break;
case 4:
numsRom[3] += nRom.I + nRom.V;
break;
case 5:
numsRom[3] += nRom.V;
break;
case 6:
case 7:
case 8:
numsRom[3] += nRom.V;
for (i = 0; i < nums[3] - 5; i++) {
numsRom[3] += nRom.I;
}
break;
case 9:
numsRom[2] += nRom.I + nRom.X;
}


return numsRom.join("");
}


console.log("Number: " + 1234 + " is " + convertToRoman(1234));

我不明白为什么每个人的解决方案都这么长,而且使用了多个 for 循环。

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;
}

在这个代码中,数字的上限可以通过向 letterTable 添加新的字母来扩展:

letterTable = {
0:{
1:'I',
5:'V',
10:'X'
},
1:{
1:'X',
5:'L',
10:'C'
},
2:{
1:'C',
5:'D',
10:'M'
},
3:{
1:'M',
5:'V', // There should be a dash over this letter
10:'X' // There should be a dash over this letter
},
// you can add new level of letters here
};


function romanLetter(i, j){
romanTable = {
'0':'',
'1':letterTable[i][1],
'2':letterTable[i][1]+letterTable[i][1],
'3':letterTable[i][1]+letterTable[i][1]+letterTable[i][1],
'4':letterTable[i][1]+letterTable[i][5],
'5':letterTable[i][5],
'6':letterTable[i][5]+letterTable[i][1],
'7':letterTable[i][5]+letterTable[i][1]+letterTable[i][1],
'8':letterTable[i][5]+letterTable[i][1]+letterTable[i][1]+letterTable[i][1],
'9':letterTable[i][1]+letterTable[i][10]
};


return romanTable[j];
}




function convertToRoman(num) {


numStr = String(num);
var result = '';
var level = 0;


for (var i=numStr.length-1; i>-1; i--){
result = romanLetter(level, numStr[i]) + result;
level++;
}


return result;
}

仍然引以为豪:)它在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<numArr.length; i++) {
if (numArr[i] < 4) {
for (var j = 0; j<numArr[i]; j++) {
romanNumeral.push(converterArray[0][numLength][0]);
}
} else if (numArr[i] < 5) {
for (var j = 3; j<numArr[i]; j++) {
romanNumeral.push(converterArray[0][numLength][1]);
}
} else if (numArr[i] < 9) {
romanNumeral.push(converterArray[0][numLength][2]);
for (var j = 5; j<numArr[i]; j++) {
romanNumeral.push(converterArray[0][numLength][0]);
}
} else if (numArr[i] < 10) {
for (var j = 8; j<numArr[i]; j++) {
romanNumeral.push(converterArray[0][numLength][3]);
}
}
numLength--;
}


return romanNumeral.join('');
}


convertToRoman(9);

虽然我的回答不如其他人的性能好,但我更关注的是不要用基数进行硬编码,让程序能够计算出其余的代码。
比如说..。
而不是:
Number = [1000,900,500,400,100,90,50,40,10,9,5,4,1] ,
Number = [‘ M’,‘ CM’,‘ D’,‘ CD’,‘ C’,‘ XC’,‘ L’,‘ XL’,‘ X’,‘ IX’,‘ V’,‘ IV’,‘ I’]

我用:

base = ['I', 'X', 'C', 'M']; pivot = ['V', 'L', 'D'];

function basicRomanNumerals(num){
let base = ['I', 'X', 'C', 'M'];
let pivot = ['V', 'L', 'D'];
return String(num).split('').reverse().map(function(num, idx){
let distance = +num - 5;
let is1AwayFromNext = Math.abs(+num - 10) === 1;
if(Math.abs(distance)=== 1 || is1AwayFromNext){
if(is1AwayFromNext){
return base[idx]+""+base[idx+1];
}else if ( distance < 0 ){
return base[idx]+""+pivot[idx];
}else{
return pivot[idx]+""+base[idx];
}
}else if(distance === 0){
return pivot[idx];
}else if(distance > 1){
return pivot[idx]+""+base[idx].repeat(+num-5);
}else{
return base[idx].repeat(+num);
}
}).reverse().join('');

我的解决方案是将数字分解成一个字符串数组,根据每个元素相对于数组长度的位置将其加上零,将新字符串中的零转换为罗马数字,然后将它们重新组合在一起。这只适用于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;
}

我刚刚在 freeCodeCamp 上完成了这个,我没有看到这个特殊的解决方案。我知道这个解决方案可以通过递归进行优化,但我只是想把它扔出去,这样至少你可以看到其他选项:

function convertToRoman(num) {
var value = [];
var temp, base, buffer;


var letters = ['I', 'V', 'X', 'L', 'C', 'D', 'M'];
var offsets = [
[1, 0],  // 1
[2, 0],  // 2
[3, 0],  // 3
[-1, 1], // 4
[0, 1],  // 5
[1, 1],  // 6
[2, 1],  // 7
[3, 1],  // 8
[-2, 2],  // 9
];


// cascade through each denomination (1000's, 100's, 10's, 1's) so that each denomination is triggered


// Thousands
if (num >= 1000) {
temp = Math.floor(num / 1000);


buffer = offsets[temp - 1];


base = 6;


value.push(getValue(base, letters, buffer));


num -= temp * 1000;
}


// Hundreds
if (num >= 100) {
temp = Math.floor(num / 100);


buffer = offsets[temp - 1];


base = 4;


value.push(getValue(base, letters, buffer));


num -= temp * 100;
}


// Tens
if (num >= 10) {
temp = Math.floor(num / 10);


buffer = offsets[temp - 1];


base = 2;


value.push(getValue(base, letters, buffer));


num -= temp * 10;
}


// Ones
if (num > 0) {


buffer = offsets[num - 1];


base = 0;


value.push(getValue(base, letters, buffer));
}


// Finish


return value.join('');
}




function getValue(base, letters, buffer) {
var val1 = buffer[0], val2 = buffer[1];
var value = [];


// If val1 is less than 0 then we know it is either a 4 or 9, which has special cases
if (val1 < 0) {
// Push the base index, then push the base plus the val2 offset
value.push(letters[base]);
value.push(letters[base + val2]);
} else {
// Push a letter if val2 is set - meaning we need to offset a number that is equal to or higher than 5
// 5 is basically the only scenario which this will exist
if (val2 > 0) value.push(letters[base + val2]);


// Now add in the next letters of the base for the inciment
for (var i = 0; i < val1; i++) {
value.push(letters[base]);
}
}


return value.join('');
}


convertToRoman(90);

我很确定伴随函数意味着它可以有几乎无限的潜力假设你提供了正确的符号来表示大于 M 的数但是不要引用我的话。

这里有一种方法,不需要循环遍历所有不同的罗马数字及其对应的数字。它有一个恒定的时间 O(1)查找,节省了一点时间复杂性。

它从右到左分解每个整数,因此2,473变成 3 + 70 + 400 + 2,000,然后使用 romanNumerals 散列表找到相应的罗马数字,并将其附加到结果字符串。它通过在查找之前向每个整数添加一个额外的 0来实现这一点,因为您要从右向左移动。这个解决方案只适用于1到3,999之间的数字。

    function integerToRoman(int) {
if (int < 1 || int > 3999) {
return -1;
}


var result = '';
var intStr = int.toString();
var romanNumerals = { 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 digit = '';


for (var i = intStr.length - 1; i >= 0; i-- ) {
if (intStr[i] === '0') {
digit += '0';
continue;
}
var num = intStr[i] + digit;
result = romanNumerals[num] + result;
digit += '0';
}


return result;
}

如果只是为了显示的目的,使用标准的 HTML 和一点 JS 作为值(如果需要的话) ,并使用 CSS 使其内联:

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;
}
<ol class="roman-lowercase"><li value="4"></li></ol> <!-- iv. -->
<ol class="roman-uppercase"><li value="142"></li></ol> <!-- CXLII. -->

const romanize = num => {
const romans = {
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
};
  

let roman = '';
  

for (let key in romans) {
const times = Math.trunc(num / romans[key]);
roman += key.repeat(times);
num -= romans[key] * times;
}


return roman;
}


console.log(
romanize(38)
)

我的解决办法是:

function convertToRoman(num) {
let romanNum = "";
const strNum = String(num);
const romans = {
1: ["I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"], // ones
2: ["X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"], // tens
3: ["C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"], // hundreds
4: ["M", "MM", "MMM"] // thousands
};


for (let i = 1; i <= strNum.length; i++)
if (Number(strNum[strNum.length - i]) !== 0)
romanNum = romans[i][strNum[strNum.length - i] - 1] + romanNum;


return romanNum;
}

它在 Chrome60-https://jsperf.com/num-to-roman中表现非常好

function convertToRoman(int) {
console.log('Number:', int);
let roman = [];
let i, k, replacement;
let seq = ['I', 'V', 'X', 'L', 'C', 'D', 'M'];


while (int > 999) {
roman.push('M');
int -= 1000;
}
while (int > 499) {
roman.push('D');
int -= 500;
}
while (int > 99) {
roman.push('C');
int -= 100;
}
while (int > 49) {
roman.push('L');
int -= 50;
}
while (int > 9) {
roman.push('X');
int -= 10;
}
while (int > 4) {
roman.push('V');
int -= 5;
}
while (int >= 1) {
roman.push('I');
int -= 1;
}


// Replace recurrences of 4 ('IIII' to 'IV')
for (i = 0; i < roman.length; i++) {
if (roman[i] == roman[i + 1] &&
roman[i] == roman[i + 2] &&
roman[i] == roman[i + 3]) {
for (k = 0; k < seq.length; k++) {
if (roman[i] == seq[k]) {
replacement = seq[k + 1];
}
}
roman.splice(i + 1, 3, replacement);
}
}


// Converting incorrect recurrences ('VIV' to 'IX')
for (i = 0; i < roman.length; i++) {
if (roman[i] == roman[i + 2] && roman[i] != roman[i + 1]) {
for (k = 0; k < seq.length; k++) {
if (roman[i] == seq[k]) {
replacement = seq[k + 1];
}
}
roman[i + 2] = replacement;
roman.splice(i, 1);
}
}


roman = roman.join('');
return roman;
}

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);

function convertToRoman(num) {
var toTen = ["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X"];
var toHungred = ["", "X" ,"XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC", "C"];
var toThousend = ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM", "M"];
var arrString = String(num).split("");
var arr = [];
if (arrString.length == 3 ){
arr.push(toThousend[arrString[+0]]);
arr.push(toHungred[arrString[+1]]);
arr.push(toTen[arrString[+2]]);
}
else if (arrString.length == 2 ){
arr.push(toHungred[arrString[+0]]);
arr.push(toTen[arrString[+1]]);
}
else if (arrString.length == 1 ){
arr.push(toTen[arrString[+0]]);
}
else if (arrString.length == 4 ) {
for (var i =1; i<=[arrString[+0]]; i++) {
arr.push("M");
}
arr.push(toThousend[arrString[+1]]);
arr.push(toHungred[arrString[+2]]);
arr.push(toTen[arrString[+3]]);
}
console.log (arr.join(""));
}


convertToRoman(36);

下面是一个正则表达式解决方案:

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;
}

自从这个问题被提出以来,我已经看过了之前46个关于“ Number-To-Roman”的解决方案,Kennebec 只有一个关于“ Roman-to-Number”的反向解决方案,这里有几个问题: “ Number”对象不能直接扩展,你需要使用原型。此外,原型设计在这种情况下也没有意义(如果有的话,String 对象是一个更好的候选对象)。其次,它不必要地复杂,而且还要调用 toRoman 方法。第三,如果数字大于4000,它就失败了。这里是一个优雅和最简洁的所有47个职位的转换类型的转换。这些转换基本上适用于任何数字。RomanToNumber 是 Gregoryr 优雅解决方案的一个小变体:

function numberToRoman(val,rom){ //returns empty string if invalid number
rom=rom||''
if(isNaN(val)||val==0)
return rom;
for(i=0;curval=[1000,900,500,400,100,90,50,40,10,9,5,4,1][i],i<13;i++)
if(val >= curval)
return numberToRoman(val-curval,rom+['M','CM','D','CD','C','XC','L','XL','X','IX','V','IV','I'][i])
}


function romanToNumber(txtRom){//returns NaN if invalid string
txtRom=txtRom.toUpperCase();
if (!/^M*(CM|CD|(D?C{0,3}))?(XC|XL|(L?X{0,3}))?(IX|IV|(V?I{0,3}))?$/.test(txtRom))
return NaN;
var retval=0;
txtRom.replace(/[MDLV]|C[MD]?|X[CL]?|I[XV]?/g, function(i) {
retval += {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 retval;
}
#tblRoman{border-collapse:collapse;font-family:sans-serif;font-size:.8em}
<h3>Roman to Number Conversion</h3>
<input type="button" value="example 1" onclick="document.getElementById('romanval').value='mmmmmmmcdlxxxiv'">
<input type="button" value="example 2" onclick="document.getElementById('romanval').value='mmmmmmmdclxxxiv'">
<input type="button" value="example 3" onclick="document.getElementById('romanval').value='mmmmmmmdxcdlxxxiv'">
<p>
Enter a Roman Number below, or click on an example button. Then click Convert
</p>
<input type="text" size="40" id="romanval">
<input type="button" onclick="document.getElementById('resultval').innerText
= romanToNumber(document.getElementById('romanval').value)" value="Convert">
<p />
Numeric Value: <b id="resultval"></b>


<hr>
<h3>Number to Roman Conversion</h3>
<input type="button" value="Generate table upto 2000" onclick="document.getElementById('tblRoman').innerHTML ='</tr>'+[...Array(2000).keys()].map(x => '<td>'+(x+1)+': '+numberToRoman(x+1)+'</td>'+((x+1)%10==0?'</tr><tr>':'')).join('')+'</tr>'">


<table id="tblRoman" border></table>

只是想知道 Piotr Berebecki 的答案。 我对它进行了编辑,这样递归函数不仅可以从给定的数字中减去1,还可以立即减去所提供数组中最高匹配的数字,以加快处理速度。

// the arrays
var arabicFormat = [1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000];
var romanFormat = ['I', 'IV', 'V', 'IX', 'X', 'XL', 'L', 'XC', 'C', 'CD', 'D', 'CM', 'M'];




function convertToRoman(num) {


// the recursion will stop here returning a blank
if (num === 0){
return '';
}


var returnValue = [];


// this is the main For loop of the function
for (var i=0; i < arabicFormat.length; i++){


if (num >= arabicFormat[i]){
// empty the array on every iteration until it gets to the final number
returnValue = [];
// store the current highest matched number in the array
returnValue.push(romanFormat[i]);
}


}


// get the correct resulting format
returnValue = returnValue.join();


// get the highest matched number value
var whatIndex = romanFormat.indexOf(returnValue);
var substractValue = arabicFormat[whatIndex];


// here the recursion happens
return returnValue + convertToRoman(num - substractValue);
}

我试图通过将阿拉伯数字的数组映射到罗马数组来实现这一点。讨厌的3级三元组可以替换为 if (){} else {}块,以使其更具可读性。它的工作时间从1到3999,但可以延长:

function romanize(num) {
if(num > 3999 || num < 1) return 'outside range!';
const roman = [ ['M', ''], [ 'C', 'D' ], [ 'X', 'L' ], [ 'I', 'V' ] ];
const arabic = num.toString().padStart(4, '0').split('');
return arabic.map((e, i) => {
return (
e < 9 ? roman[i][1].repeat(Math.floor(e / 5)) : ''
) + (
e % 5 < 4
? roman[i][0].repeat(Math.floor(e % 5))
: e % 5 === 4 && Math.floor(e / 5) === 0
? roman[i][0] + roman[i][1]
: Math.floor(e / 5) === 1
? roman[i][0] + roman[i - 1][0]
: ''
);
}).join('');
}

我觉得我的解决方案更易读,也更容易理解。

var intToRoman = function(num) {
let symbolMap = ['I','V','X','L','C','D','M','P','Q'];


if (num < 1 || num > 9999) {
return null;
}


let i = 0;
let result = '';


while (num) {
let digit = num % 10;
num = parseInt(num / 10);


switch (digit) {
case 1: result = symbolMap[i] + result;
break;
case 2: result = symbolMap[i] + symbolMap[i] + result;
break;
case 3: result = symbolMap[i] + symbolMap[i] + symbolMap[i] + result;
break;
case 4: result = symbolMap[i] + symbolMap[i+1] + result;
break;
case 5: result = symbolMap[i+1] + result;
break;
case 6: result = symbolMap[i+1] + symbolMap[i] + result;
break;
case 7: result = symbolMap[i+1] + symbolMap[i] + symbolMap[i] + result;
break;
case 8: result = symbolMap[i+1] + symbolMap[i] + symbolMap[i] + symbolMap[i] + result;
break;
case 9: result = symbolMap[i] + symbolMap[i+2] + result;
break;
}
i += 2;
}


return result;
};

有几种方法可以实现这一点,我个人比较喜欢使用对象并迭代键-值对:

const solution=(n)=>{
const romanLetters ={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};
let romanNumber ='';
let valuesArr = Object.values(romanLetters);


for(let i in valuesArr){
while (n - valuesArr[i] >= 0){
romanNumber+=Object.keys(romanLetters)[i];
n-=valuesArr[i];
}
}
return romanNumber;
}

也许最简单的解决办法是:

rome = n => {
b=0
s=''
for(a=5; n; b++,a^=7)
for(o=n%a, n=n/a^0;o--;)
s='IVXLCDM'[o>2?b+n-(n&=-2)+(o=1):b]+s
return s
}


r = [rome(892),rome(3999)];


console.log(r);

不过我不能居功,这是代码信号的 Vetalperko 的解决方案。

我真的很喜欢 jaggedsoft 的解决方案,但我不能回答,因为我的代表太低: (: (

我把它分解开来,给那些不理解它的人解释一下,希望它能帮到某些人。

function convertToRoman(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] ) { //while input is BIGGGER than lookup #..1000, 900, 500, etc.
roman += i; //roman is set to whatever i is (M, CM, D, CD...)
num -= lookup[i]; //takes away the first num it hits that is less than the input
//in this case, it found X:10, added X to roman, then took away 10 from input
//input lowered to 26, X added to roman, repeats and chips away at input number
//repeats until num gets down to 0. This triggers 'while' loop to stop.
}
}
return roman;
}




console.log(convertToRoman(36));

以下是我的代码,希望对你有所帮助:

function convertToRoman(num) {
let numArr = [];//[M,D,C,L,X,V,I]
let numStr = "";


//get num Array
numArr.push(parseInt(num / 1000));
num %= 1000;
numArr.push(parseInt(num / 500));
num %= 500;
numArr.push(parseInt(num / 100));
num %= 100;
numArr.push(parseInt(num / 50));
num %= 50;
numArr.push(parseInt(num / 10));
num %= 10;
numArr.push(parseInt(num / 5));
num %= 5;
numArr.push(num);


//cancat num String
for(let i = 0; i < numArr.length; i++) {
switch(i) {
case 0://M
for(let j = 0; j < numArr[i]; j++) {
numStr = numStr.concat("M");
}
break;
case 1://D
switch(numArr[i]) {
case 0:
                        

break;
case 1:
if(numArr[i + 1] === 4) {
numStr = numStr.concat("CM");
i++;
}else {
numStr = numStr.concat("D");
}
break;
}
break;
case 2://C
switch(numArr[i]) {
case 0:
                        

break;
case 1:
numStr = numStr.concat("C");
break;
case 2:
numStr = numStr.concat("CC");
break;
case 3:
numStr = numStr.concat("CCC");
break;
case 4:
numStr = numStr.concat("CD");
break;
}
break;
case 3://L
switch(numArr[i]) {
case 0:
                        

break;
case 1:
if(numArr[i + 1] === 4) {
numStr = numStr.concat("XC");
i++;
}else {
numStr = numStr.concat("L");
}
break;
}
break;
case 4://X
switch(numArr[i]) {
case 0:
                        

break;
case 1:
numStr = numStr.concat("X");
break;
case 2:
numStr = numStr.concat("XX");
break;
case 3:
numStr = numStr.concat("XXX");
break;
case 4:
numStr = numStr.concat("XL");
break;
}
break;
case 5://V
switch(numArr[i]) {
case 0:
                        

break;
case 1:
if(numArr[i + 1] === 4) {
numStr = numStr.concat("IX");
i++;
}else {
numStr = numStr.concat("V");
}
break;
}
break;
case 6://I
switch(numArr[i]) {
case 0:
                        

break;
case 1:
numStr = numStr.concat("I");
break;
case 2:
numStr = numStr.concat("II");
break;
case 3:
numStr = numStr.concat("III");
break;
case 4:
numStr = numStr.concat("IV");
break;
}
break;
}
}
console.log(numStr);
return numStr;
}


convertToRoman(3999);

这是我的单循环解决方案

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 romanNum = "";


for(key in roman){
var check = num>=roman[key];
if(check){
console.log(romanNum);
romanNum += key;
num-= roman[key];
}
}
return romanNum
}


convertToRoman(150);
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 result = '';
for (var key in roman) {
if (num == roman[key]) {
return result +=key;
}
var check = num > roman[key];
if(check) {
result = result + key.repeat(parseInt(num/roman[key]));
num = num%roman[key];
}
}
return result;
}


console.log(convertToRoman(36));

这个解决方案只运行一个循环,并且使用最小对象将数字映射为罗马字母

function RomantoNumeral(r){
let result = 0,
keys = {M:1000, D:500, C:100, L:50, C:100, L:50, X:10, V:5, I:1},
order = Object.keys(keys),
rom = Array.from(r)


rom.forEach((e, i)=>{
if( i  < rom.length -1 && order.indexOf(e) > order.indexOf(rom[i+1])){
result -= keys[e]
} else {
result +=keys[e]
}
})
return result
}


RomantoNumeral('MMDCCCXXXVII') #2837

循环可能更优雅,但我发现它们很难阅读。提出了一个或多或少的硬编码版本,很容易的眼睛。只要你理解了第一行,剩下的就是显而易见的了。

function romanNumeralGenerator (int) {
let roman = '';


roman +=  'M'.repeat(int / 1000);  int %= 1000;
roman += 'CM'.repeat(int / 900);   int %= 900;
roman +=  'D'.repeat(int / 500);   int %= 500;
roman += 'CD'.repeat(int / 400);   int %= 400;
roman +=  'C'.repeat(int / 100);   int %= 100;
roman += 'XC'.repeat(int / 90);    int %= 90;
roman +=  'L'.repeat(int / 50);    int %= 50;
roman += 'XL'.repeat(int / 40);    int %= 40;
roman +=  'X'.repeat(int / 10);    int %= 10;
roman += 'IX'.repeat(int / 9);     int %= 9;
roman +=  'V'.repeat(int / 5);     int %= 5;
roman += 'IV'.repeat(int / 4);     int %= 4;
roman +=  'I'.repeat(int);


return roman;
}

const basicRomanNumeral =
['',
'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','MM','MMM'
];


function convertToRoman(num) {
const numArray = num.toString().split('');
const base = numArray.length;
let count = base-1;
const convertedRoman = numArray.reduce((roman, digit) => {
const digitRoman = basicRomanNumeral[+digit + count*10];
const result = roman + digitRoman;
count -= 1;
return result;
},'');
return convertedRoman;
}

    const convertToRoman = (n)=>
{
let u =0;
let result ='';
let rL='IVXLCDM';


while (n>0)
{
u=n%10;
switch (u){
case 1: result =   rL[0] + result ;
break;
case 2: result = rL[0]+rL[0] + result;
break;
case 3: result = rL[0]+rL[0]+rL[0] + result;
break;
case 4: result = rL[0]+rL[1] + result;
break;
case 5: result =  rL[1] + result;
break;
case 6: result = rL[1] + rL[0] + result;
break;
case 7: result =rL[1] + rL[0] +rL[0] + result;
break;
case 8: result =  rL[1] + rL[0] +rL[0] + rL[0] + result;
break;
case 9: result =  rL[0] + rL[2] + result;
break;
};
rL = rL.substring(2)
// after every last digit.. when conversion is finished..
// number is taking another value - same as container with roman Letter




n=Math.trunc(n/10);
};
return result;
};

I'm beginner, and I see like that ))) without arrays . of course it would be better with itter + acc in function.. 刚刚通过了 freeCodeCamp 的测试

我还没有看到这个帖子,所以这里有一个有趣的解决方案,只使用字符串操作:

var numbers = [1, 4, 5, 7, 9, 14, 15, 19, 20, 44, 50, 94, 100, 444, 500, 659, 999, 1000, 1024];
var romanNumeralGenerator = function (number) {
return 'I'
.repeat(number)
.replace(/I{5}/g, 'V')
.replace(/V{2}/g, 'X')
.replace(/X{5}/g, 'L')
.replace(/L{2}/g, 'C')
.replace(/C{5}/g, 'D')
.replace(/D{2}/g, 'M')
.replace(/DC{4}/g, 'CM')
.replace(/C{4}/g, 'CD')
.replace(/LX{4}/g, 'XC')
.replace(/X{4}/g, 'XL')
.replace(/VI{4}/g, 'IX')
.replace(/I{4}/g, 'IV')
};


console.log(numbers.map(romanNumeralGenerator))

    var romanToInt = function(s) {
var sum = [];
var obj = {"I":1,"V":5,"X":10,"L":50,"C":100,"D":500,"M":1000};
for(var i=0;i<s.length;i++){
if(obj[s[i]]>obj[s[i-1]]){
sum[i-1] = (obj[s[i]]-obj[s[i-1]])
}else{
sum[i]=(obj[s[i]])
}
}
return sum.reduce((a, b) => a + b, 0);
};

上面的代码使用一个对象查找这些值并进行相应的计算。

    var romanToInt = function(s) {
var sum = [];


for(var i=0;i<s.length;i++){


if(s[i]=="I"){
sum.push(1);
}else if(s[i]=="V"){
sum.push(5);
}else if(s[i]=="X"){
sum.push(10);
}else if(s[i]=="L"){
sum.push(50);
}else if(s[i]=="C"){
sum.push(100);
}else if(s[i]=="D"){
sum.push(500);
}else if(s[i]=="M"){
sum.push(1000);
}


if(sum[i-1]<sum[i]){
sum[i] = sum[i]-sum[i-1]
sum[i-1] = 0
}else{
sum[i] = sum[i]
}


}


return sum.reduce((a, b) => a + b, 0)


};

上述情况下的代码使用 if/else-if 语句执行相同的操作。此方法执行速度更快,而且内存效率更高。

使用 switch 语句也可以按以下方式进行求解。

  var romanToInt = function(s) {
var sum = [];


for(var i=0;i<s.length;i++){


switch(s[i]){
case "I":
sum.push(1);
break;
case "V":
sum.push(5);
break;
case "X":
sum.push(10);
break;
case "L":
sum.push(50);
break;
case "C":
sum.push(100);
break;
case "D":
sum.push(500);
break;
case "M":
sum.push(1000);
break;
}


if(sum[i-1]<sum[i]){
sum[i] = sum[i]-sum[i-1]
sum[i-1] = 0
}else{
sum[i] = sum[i]
}


}


return sum.reduce((a, b) => a + b, 0)


};

我的解决办法是:

var roman = "MX";


function solution(roman) {
var val = 0;
for (let i = 0; i < roman.length; i++) {
if (roman.charAt(i) == 'I') {
if (roman.charAt(i + 1) == 'V') {
val += 4;   // IV
} else if (roman.charAt(i + 1) == 'X') {
val += 9;   // IX
} else {
val += 1;   // I
}
} else if (roman.charAt(i) == 'V') {
if (roman.charAt(i - 1) == 'I') {
val = val;
} else {
val += 5;   // V
}
} else if (roman.charAt(i) == 'X') {
if (roman.charAt(i - 1) == 'I') {   // Check if there is I before X
val = val;
}else if (roman.charAt(i + 1) == 'L') {
val += 40;  // XL
} else if (roman.charAt(i + 1) == 'C') {
val += 90;  // XC
} else {
val += 10;  // X
}
} else if (roman.charAt(i) == 'L') {
if (roman.charAt(i - 1) == 'X') {   // Check if there is X before L
val = val;
} else {
val += 50;  // L
}
} else if (roman.charAt(i) == 'C') {
if (roman.charAt(i - 1) == 'X') {
val = val;  // XC
}else if (roman.charAt(i + 1) == 'D') {
val += 400;  // CD
} else if (roman.charAt(i + 1) == 'M') {
val += 900;  // CM
} else {
val += 100;  // C
}
} else if (roman.charAt(i) == 'D') {
if (roman.charAt(i - 1) == 'C') {
val = val;  // CD
} else {
val += 500; // D
}
} else if (roman.charAt(i) == 'M') {
if (roman.charAt(i - 1) == 'C') {
val = val;  // CM
} else {
val += 1000; // M
}
}
}
return val;
}
console.log(solution(roman));  // The answer is: 1010

使用以下代码:

function convertNumToRoman(num){
const romanLookUp = {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}
let result = ''


// Sort the object values to get them to descending order
Object.keys(romanLookUp).sort((a,b)=>romanLookUp[b]-romanLookUp[a]).forEach((key)=>{
while(num>=romanLookUp[key]){
result+=key;
num-=romanLookUp[key]
}
})
return result;
}

回答得不错。您可以通过编程方式完成这项工作,而无需对这些值进行过多的硬编码。只是你的代码会稍微长一点。

const convertToRoman = (arabicNum) => {
const roman_benchmarks = {1: 'I', 5: 'V', 10: 'X', 50: 'L', 100: 'C', 500: 'D', 1000: 'M', 5000: '_V', 10000: '_X', 50000: '_L', 100000: '_C'};
// in the future, you can add higher numbers with their corresponding roman symbols/letters and the program will adjust to the change
// const arabic_benchmarks = [1, 5, 10, 50, 100, 500, 1000, 5000, 10000, 50000, 100000];   // don't forget to include the new numbers here too
const arabic_benchmarks = Object.keys(roman_benchmarks);


arabicNum = parseInt(arabicNum);
let proceed = parseInt(arabicNum.toString().length);
let romanNumeral = '';
while(proceed){     // the loop continues as long as there's still a unit left in arabicNum
const temp_denominator = 1 * (10**(arabicNum.toString().length-1)); // determine what multiple of 10 arabicNum is
const multiple = Math.floor(arabicNum/temp_denominator);        // get its first digit
const newNum = multiple*temp_denominator;       // regenerate a floored version of arabicNum
const filtered_two = arabic_benchmarks.filter((x, i) => newNum >= x && newNum<= arabic_benchmarks[i+1] || newNum <= x && newNum>= arabic_benchmarks[i-1]);
// filter arabic_benchmarks for the 2 boundary numbers newNum falls within
switch (newNum) {   // check for what roman numeral best describes newNum and assign it to romanNumeral
case (newNum == filtered_two[0]-temp_denominator ? newNum :''):
romanNumeral += roman_benchmarks[temp_denominator]+roman_benchmarks[filtered_two[0]]
break;
case (newNum == filtered_two[0] ? newNum : ''):
romanNumeral += roman_benchmarks[filtered_two[0]]
break;
case (newNum > filtered_two[0] && newNum < (filtered_two[1]-temp_denominator) ? newNum : ''):
romanNumeral += roman_benchmarks[filtered_two[0]]
const factor = multiple < 5 ? (multiple%5)-1 : multiple%5;
for(let i = 0; i < factor; i++){
romanNumeral += roman_benchmarks[temp_denominator];
}
break;
case (newNum == filtered_two[1]-temp_denominator ? newNum : ''):
romanNumeral += roman_benchmarks[temp_denominator]+roman_benchmarks[filtered_two[1]];
break;
case (newNum == filtered_two[1] ? newNum : ''):
romanNumeral += roman_benchmarks[filtered_two[1]];
break;
default:
break;
}


arabicNum = arabicNum - newNum; // reduce arabicNum by its first hierarchy
proceed--; // continue the loop
}
    

return romanNumeral;
}




function atalakit (num) {
var result ="";
var roman = ["MMM", "MM", "M", "CM", "DCCC", "DCC", "DC", "D", "CD", "CCC", "CC", "C", "XC", "LXXX", "LXX", "LX", "L", "XL", "XXX", "XX", "XI", "X", "IX", "VIII", "VII", "VI", "V", "IV", "III", "II", "I"];
var arabic = [3000, 2000, 1000, 900, 800, 700, 600, 500, 400, 300, 200, 100, 90, 80, 70, 60, 50, 40, 30, 20, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
if ( num>0 && num<4000) {
var arabiclength = arabic.length;
for ( i=0; arabiclength > i; i++) {
if (Math.floor(num/arabic[i])>0){
result += roman[i];
num -= arabic[i];
}
}
}
else {
document.getElementById('text').innerHTML = "too much";
}
document.getElementById('text2').innerHTML = result;
}

这是我的

function convertToRoman(num) {
let decimalValueArray = [1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000, "bigger"];
let romanNumArray = ["I", "IV", "V", "IX", "X", "XL", "L", "XC", "C", "CD", "D", "CM", "M"];
let resultNumArray = [];
function getRoman(num) {
for (let i = 0; i < decimalValueArray.length; i++) {
let decimalElem = decimalValueArray[i];
if (num === decimalElem || num === 0) {
resultNumArray.push(romanNumArray[i]);
return ;


} else if (decimalElem > num || decimalElem === "bigger") {   //using (decimalElem>num) and then array value of(i-1) to get the highest decimal value from the array.but this doesnt work when highest decimel value is 1000.so added  "bigger" element.
resultNumArray.push(romanNumArray[i - 1]);
getRoman(num - (decimalValueArray[i - 1]));
} else {
continue;
}
return;
}
}
getRoman(num);
let resultNumber = (resultNumArray.join(""));
return(resultNumber);    }

下面是递归的解决方案,看起来很简单:

const toRoman = (num, result = '') => {
const map = {
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,
};
for (const key in map) {
if (num >= map[key]) {
if (num !== 0) {
return toRoman(num - map[key], result + key);
}
}
}
return result;
};
console.log(toRoman(402)); // CDII
console.log(toRoman(3000)); // MMM
console.log(toRoman(93)); // XCIII
console.log(toRoman(4)); // IV

字符串方式: (M 以下)

        const romanNumerals =   [
['I', 'V', 'X'],//for ones 0-9
['X', 'L', 'C'],//for tens 10-90
['C', 'D', 'M'] //for hundreds 100-900
];
        

function romanNumUnderThousand(dijit, position) {
let val = '';
if (position < 3) {
const [a, b, c] = romanNumerals[position];
switch (dijit) {
case '1': val = a;              break;
case '2': val = a + a;          break;
case '3': val = a + a + a;      break;
case '4': val = a + b;          break;
case '5': val = b;              break;
case '6': val = b + a;          break;
case '7': val = b + a + a;      break;
case '8': val = b + a + a + a;  break;
case '9': val = a + c;          break;
}
}
return val;
}
    

function convertToRoman(num) {
num = parseInt(num);
const str_num = num.toString();
const lastIndex = str_num.length - 1;
return [
`${(num > 999) ? 'M'.repeat(parseInt(str_num.slice(0, lastIndex - 2))) : ''}`,
`${(num > 99) ? romanNumUnderThousand(str_num[lastIndex - 2], 2) : ''}`,
`${(num > 9) ? romanNumUnderThousand(str_num[lastIndex - 1], 1) : ''}`,
romanNumUnderThousand(str_num[lastIndex], 0)
].join('');
}
convertToRoman(36);
function convertToRoman(num) {


let I = 1
let IV = 4
let V = 5
let IX = 9
let X = 10
let XL = 40
let L = 50
let XC = 90
let C = 100
let CD = 400
let D = 500
let CM = 900
let M = 1000


let arr = []
while(num > 0) {
console.log(num)
switch(true) {


case num - M >= 0 :
arr.push('M')
num -= M
break
case num - CM >= 0 :
arr.push('CM')
num -= CM
break
case num - D >= 0 :
arr.push('D')
num -= D
break
case num - CD >= 0 :
arr.push('CD')
num -= CD
break
case num - C >= 0 :
arr.push('C')
num -= C
break
case num - XC >= 0 :
arr.push('XC')
num -= XC
break
case num - L >= 0 :
arr.push('L')
num -= L
break
case num - XL >= 0 :
arr.push('XL')
num -= XL
break
case num - X >= 0 :
arr.push('X')
num -= X
break
case num - IX >= 0 :
arr.push('IX')
num -= IX
break
case num - V >= 0 :
arr.push('V')
num -= V
break
case num - IV >= 0 :
arr.push('IV')
num -= IV
break
case (num - I) >= 0 :
arr.push('I')
num -= I
break
}
}


str = arr.join("")


return str
}
function convertToRoman(num: number){
let integerToRomanMap = new Map<number, string>([
[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"]
])
if(integerToRomanMap.has(num)){
return integerToRomanMap.get(num)
}
let res = ''
while(num > 0){
let len = String(num).length;
let divisor = Math.pow(10, len - 1)
let quotient = Math.floor(num/divisor)
num = num % divisor
if(integerToRomanMap.has(divisor * quotient)){
res += integerToRomanMap.get(divisor * quotient)
}else{
while(quotient > 0){
res += integerToRomanMap.get(divisor)
quotient--;
}
}
}
return res;
}

给你。

function check(digit, char1, char2, char3) {
if(digit <=3) {
return char1.repeat(digit)
}if(digit == 4){
return char1+char2
}if(digit == 5) {
return char2
}if (digit > 5 && digit < 9) {
return char2+char1.repeat(digit-5)
}if(digit == 9) {
return char1+char3
}
}


function convertToRoman(num) {
let result;
let numList = String(num).split("").reverse()
result = [check(parseInt(numList[0]), 'I', 'V', 'X'),check(parseInt(numList[1]), 'X', 'L', 'C'),check(parseInt(numList[2]), 'C', 'D', 'M'),'M'.repeat(parseInt(numList[3]))]


return result.reverse().join('');
}


let res = convertToRoman(2);
console.log(res)

如果有人需要的话就加个大号

function convertToRoman(num) {


if (num < 1 ) {
console.error('Error (fn convertToRoman(num)): Can\'t convert negetive numbers. You provided: ' + num);
return false;
}
if (+num > 3000000) {
console.error('Error (fn convertToRoman(num)): Can\'t convert numbers greater than 3000000. You provided: ' + num);
return false;
}
if (!+num) {
console.error('Error (fn convertToRoman(num)): \'num\' must be a number or number in a string. You provided: ' + num);
return false;
}


function num2let(a, b, c, num) {
if(num < 4) return a.repeat(num);
else if (num === 4) return a + b;
else if (num < 9) return b + a.repeat(num - 5);
else return a + c;
}


let romanArray = ["I", "V", "X", "L", "C", "D", "M", "Vb", "Xb", "Lb", "Cb", "Db", "Mb"]; // Xb means Xbar


let arr = String(+num).split('').map(el => +el);
let len = arr.length;
let roman = "";
arr.forEach(el => {
let index = (len - 1) * 2;
roman += num2let(romanArray[index], romanArray[index  + 1], romanArray[index + 2], el);
len--;
});


return roman;
}

var intToRoman = function(value) {
const romanObj = {
1: 'I',
2: 'II',
3: 'III',
4: 'IV',
5: 'V',
6: 'VI',
7: 'VII',
8: 'VIII',
9: 'IX',
10: 'X',
40: 'XL',
50: 'L',
60:'LX',
70: 'LXX',
80:'LXXX',
90: 'XC',
100: 'C',
400: 'CD',
500: 'D',
600: 'DC',
700:'DCC',
800:'DCCC',
900: 'CM',
1000:'M'
};
let romanValue = '';
while(value>0){
let x = value.toString().length - 1;
let y = x == 0 ? 0 : 10 ** x;
if(!y) { romanValue += romanObj[value], value=0; }
else {
            

let temp = value % y;
let multiple = Math.floor(value/y);
if (romanObj[multiple*y]) {
romanValue+=romanObj[multiple*y];
} else {
console.log('logger of 1996', romanObj[y], y);
romanValue+=romanObj[y].repeat(multiple);
}
value=temp;
}
}
return romanValue;
}


console.log(intToRoman(18))

它的工作时间是从1到9999。如果有可能存在一个罗马数字为10000,只需将其替换为罗马数字,并创建另一个限制为99999。

function convertToRoman(num) {
const numArray = num.toString().split("")
const roman = {
1: "I",
5: 'V',
10: 'X',
50: 'L',
100: 'C',
500: "D",
1000: 'M',
9999: "LIMIT"
}


let numLen = numArray.length;
let converted = numArray.map((x) => {
numLen--;
return x + "0".repeat(numLen)
})


let trans = converted.map((x) => {
let last = "";


for (let key in roman) {
if (x.charAt(0) == 0) {
return ""
}


if (key == x) {
return roman[key];
}


if (key > parseInt(x) && last < parseInt(x)) {
if (last.length == key.length) {
const ave = (parseInt(last) + parseInt(key)) / 2


if (x > ave) {
return roman[last] + roman[key]
}


return roman[last].repeat(x.charAt(0));
}


if (x.charAt(0) == 9) {
return roman[key.slice(0, key.length - 1)] + roman[key];
}


return roman[last] + roman[key.slice(0, key.length - 1)].repeat(x.charAt(0) - 5)
}


last = key
}
})


return trans.join("");
}


for(let i = 1; i < 12; i++) {
console.log(i, "->", convertToRoman(i))
}

宝宝的糖果。

首先,你必须将 romam 映射到一个对象中的基数:

const _numbersMap = {
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
}


/* The CM, CD, XC, XL, IX and IV properties are
only needed for the cardinalToRoman() function below. */

注意: 如果你只需要将 roman 转换为 cardinal,那么你就不需要上面对象中有两个 roman 字符的属性了。

然后构建一个函数来完成从基数到罗马数字的神奇转换:

// The funciton receives a cardinal as parameter (of integer type)
const cardinalToRoman = num => {


// M is the last char in the roman numeric system. Just preventing crashes.
if (num >= 4000) {
console.log('Number is too big');
return
}


let roman = ''; // The initial roman string


// It iterates over the _numbersMap object's properties
for (var i of Object.keys(_numbersMap)) {


/* For each iteration, it will calculate the division of the
given number by the value of the property beeing iterated. */
var q = Math.floor(num / _numbersMap[i]);


/* So the value, multiplied by the current property's value,
will be subtracted from the given number */
num -= q * _numbersMap[i];


/* The result will be the times that the key of the
current property (its respective roman sting) will be repeated
in the final string */
roman += i.repeat(q);
}


return roman;
};

最后,如果你想做逆运算,那么构建一个函数来将 Roman 转换为基数整数:

// The funciton receives a roman number as parameter (of srting type)
const romanToCardinal = roman => {


let num = 0; // Initial integer number
    

/* Let's split the roman string in a Array of chars, and then
put it in reverse order */
const romansArray = Array.from(roman).reverse();
    

// Then let's iterate the array
romansArray.forEach((char, index, array) => {
            

/* We take the integer number corresponding to the current
and the previous chars in the iteration. */
const currentNumChar = _numbersMap[char];
const prevNumChar = _numbersMap[array[index - 1]];
        

// Throws error if the char is unknown.
if (!currentNumChar) {
console.error(`The charecter "${char}" of the given roman number "${roman}" is invalid as a roman number char.`);
return false;
}
        

/* The integer corresponding to the current char is
subtracted from the result if it's bigger than the previous
integer. If itsn't, the integer is summed to the result */
if (prevNumChar && prevNumChar > currentNumChar) {
num -= currentNumChar;
} else {
num += currentNumChar;
}
        

});
    

return num;
}

试试 JSFiddle频道。

递归,转换前加1,转换后减1:

const toRoman = (num, i="I", v="V", x="X", l="L", c="C", d="D", m="M") =>
num ? toRoman(num/10|0, x, l, c, d, m, "?", "?", num%=10) +
(i + ["",v,x][++num/5|0] + i.repeat(num%5)).replace(/^(.)(.*)\1/, "$2")
: "";


console.log(toRoman(3999));

我创建了两个转换函数。

第一个函数可以使用 reduce 将数字转换为 Roman。 第二个函数和第一个函数非常相似,函数使用相同的方法来转换值。

您需要更改的所有内容都是 _roman属性。因为你必须用你想要的比例来扩展这个常数,我把最大值放在 1000上,但是你可以放更多。

更大的规模与罗马数字,你可以在这里找到 https://www.tuomas.salste.net/doc/roman/numeri-romani.html

const _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 };


// 1903 => MCMIII
function toRoman(number = 0) {
return Object.keys(_roman).reduce((acc, key) => {
while (number >= _roman[key]) {
acc += key;
number -= _roman[key];
}
return acc;
}, '');
}




// MCMIII => 1903
function fromRoman(roman = '') {
return Object.keys(_roman).reduce((acc, key) => {
while (roman.indexOf(key) === 0) {
acc += _roman[key];
roman = roman.substr(key.length);
}
return acc;
}, 0);
}


console.log(toRoman(1903));  // should return 'MCMIII
console.log(fromRoman('MCMIII')); // should return 1903

let converter={
I : 1, II: 2, III:3, IV:4, V:5, VI:6, VII:7, VIII:8, IX:9
}
let converter1={
X:10,XX:20,XXX:30,XL:40,L:50,LX:60,LXX:70,LXXX:80,XC:90
}
let converter2={
C:100,CC:200,CCC:300,CD:400,D:500,DC:600,DCC:700,DCCC:800,CM:900
}


let result= []
function convertToRoman(number){


if(number >= 1000){
let l = 'M'
result.push(l.repeat(number/1000))
if(number%1000  < 1000){
number = number%1000
}
}
if(100 <=number && number <= 999){
let border = String(number)[0]
for(let i=0; i <= Number(border); i++){
if(Object.values(converter2)[i]/ Number(border) == 100){
result.push(Object.keys(converter2)[i])
number = number-Object.values(converter2)[i]


}
}
}
if(10 <= number && number <= 99){


let border= String(number)[0]


for(let i = 0; i < Number(border) ; i++){
if(Object.values(converter1)[i]===  Number(border)*10  ){
result.push(Object.keys(converter1)[i])
number = number-Object.values(converter1)[i]
}
}
}


if(number <= 9){
for(let i = 0; i <= number; i++){
if(Object.values(converter)[i] == number){
result.push(Object.keys(converter)[i])
result = result.join("")
result = String(result)
return result
}
}
}
result = result.join("")
result = String(result)
return result
}




console.log(convertToRoman(9))

这个解决方案可以用于小数目(1-23)。它可以用于例如城市地区。

var rom = [[23,'XXIII'],[18,'XVIII'],[22,'XXII'],[17,'XVII'],[13,'XIII'],[ 8,'VIII'],[21,'XXI'],[19,'XIX'],[16,'XVI'],[ 3,'III'],[ 7,'VII'],[14,'XIV'],[12,'XII'],[ 2,'II'],[ 6,'VI'],[ 4,'IV'],[ 9,'IX'],[11,'XI'],[15,'XV'],[20,'XX'],[ 1,'I'],[ 5,'V'],[10,'X']];
var i2r = (x)=> rom.filter(y=>y[0]==x).pop()?.[1];
var r2i = (x)=> rom.map(y=>x.includes(y[1])?y[0]:0).filter(y=>y).shift();

我觉得这个解决方案可以帮助你更好地理解这个问题

const romanNumeral = function (num) {
let roman = "";
let nums = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
let romans = [
"M",
"CM",
"D",
"CD",
"C",
"XC",
"L",
"XL",
"X",
"IX",
"V",
"IV",
"I",
];
for (let i = 0; i < nums.length; i++) {
while (num >= nums[i]) {
roman += romans[i];
num -= nums[i];
}
return roman;
};

简单来说

function convertToRoman (num) {
const romanList = {
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
}
let roman = "";
Object.keys(romanList).forEach((key, index) => {
let temp = parseInt(num / romanList[key]);
num = num % romanList[key];
roman = roman + key.repeat(temp);
});


return roman;
};

一个非递归的无循环解决方案,其中包含嵌套的咖喱函数:

const convert =
(base, sym, next) =>
(num, res = '') =>
next && num
? next(num % base, res + sym.repeat(num / base))
: res + sym.repeat(num);


const roman = convert(1000,  'M',
convert( 900, 'CM',
convert( 500,  'D',
convert( 400, 'CD',
convert( 100,  'C',
convert(  90, 'XC',
convert(  50,  'L',
convert(  40, 'XL',
convert(  10,  'X',
convert(   9, 'IX',
convert(   5,  'V',
convert(   4, 'IV',
convert(   1,  'I')))))))))))));


roman(1999); //> 'MCMXCIX'

它是怎么工作的?

我们定义了一个 convert函数,它接受一个基数(base)、它的罗马数字(sym)和一个可选的 next函数,我们将在下一次转换中使用这个函数。然后它返回一个函数,该函数接受一个要转换的数字(num)和一个用于累加以前的转换的可选字符串(res)。

例如:

const roman =
convert(1000, 'M', (num, res) => console.log(`num=${num}, res=${res}`));
//        ^^^^  ^^^  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//        base  sym  next


roman(3999);
// LOG: num=999, res=MMM

请注意,roman是由 convert返回的函数: 它接受一个数字(num)和一个可选的字符串 res.这是相同的签名作为 next功能..。

这意味着我们可以使用 convert返回的函数作为 next函数!

const roman =
convert(1000, 'M',
convert(900, 'CM', (num, res) => console.log(`num=${num}, res=${res}`)));


roman(3999);
// LOG: num=99, res=MMMCM

因此,我们可以继续嵌套 convert函数来覆盖整个罗马数字转换表:

const roman =
convert(1000,  'M',
convert( 900, 'CM',
convert( 500,  'D',
convert( 400, 'CD',
convert( 100,  'C',
convert(  90, 'XC',
convert(  50,  'L',
convert(  40, 'XL',
convert(  10,  'X',
convert(   9, 'IX',
convert(   5,  'V',
convert(   4, 'IV',
convert(   1,  'I')))))))))))));

如果没有定义 next,那就意味着我们到达了转换表的末尾: convert(1, 'I'),就像重复 'I' N次一样简单,例如 3-> 'I'.repeat(3)-> 'III'

num检查是一种提前退出条件,用于当没有可转换的内容时,例如 3000-> MMM

didn't see a matrix array being used together with a for and a nested ternary operator, looks fancy but it's barely out of the hard-code zone, hope you like it!.

function rome(num) {
if (num > 3999) {return 'number too large'};
let strNum = JSON.stringify(num).split("");
let number = [];
let romans = [ ['I','IV','V','IX'],
['X','XL','L','XC'],
['C','CD','D','CM'],
['M','','','']      ];
for (let j = strNum.length - 1 ; 0 <= j; j--){
let digit ='';
digit = strNum[j] == 0 ?  '' :
strNum[j] <= 3 ?
romans[strNum.length-1-j][0].repeat(Number(strNum[j])) :
strNum[j] == 4 ? romans[strNum.length-1-j][1] :
strNum[j] == 5 ? romans[strNum.length-1-j][2] :
strNum[j] <= 8 ? romans[strNum.length-1-j][2] +
romans[strNum.length-1-j][0].repeat(Number(strNum[j])-5) :
romans[strNum.length-1-j][3] ;
number.unshift(digit);
};
return ''.concat(number.join(''));
}

我就是这么解决的。其逻辑是,罗马数字遵循从1到9的规则,只是根据数字的索引更改字母。

function convertToRoman(num) {
const roman = {1: 'I', 2: 'II', 3: 'III', 4: 'IV', 5: 'V', 6: 'VI', 7: 'VII', 8: 'VIII', 9: 'IX'}
  

return num
.toString()
.split('')
.reverse()
.map((n, i) =>
(i == 0) ? roman[n] :
(i == 1 && n != 0) ?
roman[n]
.split('')
.map(a =>
(a == 'I') ? 'X' :
(a == 'V') ? 'L' :
(a == 'X') ? 'C' : '')
.join('') :
(i == 2 && n != 0) ?
roman[n]
.split('')
.map(a =>
(a == 'I') ? 'C' :
(a == 'V')  ? 'D' :
(a == 'X')  ? 'M' : '')
.join('') :
(i == 3 && n != 0) ?
roman[n]
.split('')
.map(a => a == 'I' ? 'M' : '')
.join('') : '')
.reverse()
.join('')
}

这是我找到的最简单的方法。

class RomanNumeral {
constructor(value, symbol){
this.value = value;
this.symbol = symbol;
}
}


const romanNumerals = [
new RomanNumeral(1000, "M"),
new RomanNumeral(900, "CM"),
new RomanNumeral(500, "D"),
new RomanNumeral(400, "CD"),
new RomanNumeral(100, "C"),
new RomanNumeral(90, "XC"),
new RomanNumeral(50, "L"),
new RomanNumeral(40, "XL"),
new RomanNumeral(10, "X"),
new RomanNumeral(9, "IX"),
new RomanNumeral(5, "V"),
new RomanNumeral(4, "IV"),
new RomanNumeral(1, "I"),
];


function roman(number) {
assertNumberInRomanLimits(number);
let result = "";
for (const { value , symbol  } of romanNumerals){
while(number >= value){
result += symbol;
number -= value;
}
}
return result;
}


function assertNumberInRomanLimits(number) {
if (number > 3999) {
throw new RangeError("The biggest number we can form in Roman numerals is MMMCMXCIX (3999).");
}
if (number < 1) {
throw new RangeError("There is no concept of 0 or negatives in Roman numerals.");
}
};


console.log(roman(3)); //=> "III"


console.log(roman(47)); //=> "XLVII"


console.log(roman(3990)); //=> "MMMCMXC"


console.log(roman(3999)); //=> "MMMCMXCIX"


console.log(roman(1984)); //=> "MCMLXXXIV"

如果您想使用这个模块,您可以

Https://github.com/ultirequiem/roman.js

Https://ulti.js.org/roman.js

它包括100% 的代码覆盖率、 TypeScript 类型和文档。

只是想发表我对 stackoverflow 的第一个评论:)

function convertToRoman(num) {
let romanNum = [
[1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000, 4000],
[
"I",
"IV",
"V",
"IX",
"X",
"XL",
"L",
"XC",
"C",
"CD",
"D",
"CM",
"M",
null,
],
];


let romanConv = "";


for (let i = 0; i < 4; i++) {
for (let j = 0; j < romanNum[0].length; j++) {
if (num >= romanNum[0][j] && num < romanNum[0][j + 1]) {
let x = parseInt(num / romanNum[0][j]);
romanConv += romanNum[1][j].repeat(x);
num %= romanNum[0][j];
}
}
}


return romanConv;
}


console.log(convertToRoman(3999));

我认为我的答案是一个概念性的学习方法,很清楚为什么会发生这种情况

var initialValue = {
I: 1,
V: 5,
X: 10,
L: 50,
C: 100,
D: 500,
M: 1000
};


var romanToInt = function (s) {
let defaultNumber = 0;
for (let i = 0; i < s.length; i++) {
if (s[i] === "I" && s[i + 1] === "V") {
return (defaultNumber += 4);
i++;
} else if (s[i] === "I" && s[i + 1] === "I" && s[i + 2] === "I") {
return (defaultNumber += 3);
i++;
} else if (s[i] === "I" && s[i + 1] === "I") {
return (defaultNumber += 2);
i++;
} else if (s[i] === "I" && s[i + 1] === "X") {
return (defaultNumber += 9);
i++;
} else if (s[i] === "C" && s[i + 1] === "M") {
defaultNumber += 900;
i++;
} else if (s[i] === "X" && s[i + 1] === "C") {
defaultNumber += 90;
i++;
} else if (s[i] === "C" && s[i + 1] === "D") {
defaultNumber += 400;
i++;
} else if (s[i] === "X" && s[i + 1] === "L") {
defaultNumber += 40;
i++;
} else {
defaultNumber += initialValue[s[i]];
}
}


return defaultNumber;
};


romanToInt("MCMXCIV");

这就是我对这个问题的回答:

const key1 = ["I", "IV", "V", "IX"];
const key2 = ["X", "XL", "L", "XC"];
const key3 = ["C", "CD", "D", "CM"];
const key4 = ["M"];
const keys = [key1, key2, key3, key4];


function convertToRoman(num) {
const numArray = Array.from(String(num)).reverse();


let arr = numArray.map((el, i) => {
let rom = [];


if (el <= 3) {
for (let t = 1; t <= el; t++) {
rom.push(keys[i][0]);
}
} else if (el == 4) {
rom.push(keys[i][1]);
} else if (el >= 5 && el < 9) {
rom.push(keys[i][2]);
if (el > 5) {
let dif = el - 5;
for (let t = 1; t <= dif; t++) {
rom.push(keys[i][0]);
}
}
} else rom.push(keys[i][3]);


return rom.flat().join("");
});
res = arr.reverse().flat().join("");
console.log(res);
return res;
}
    

convertToRoman(365);

function convertToRoman(num) {
let roman = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"];
let arabic = [1000, 900, 500, 400, 100,  90,   50,  40,   10,   9,   5,   4,    1];
let index = 0;
let result = "";
while (num > 0) {
if (num >= arabic[index]) {
result += roman[index];
num -= arabic[index];
} else index++;
}


return result;
}

我知道这里没有人需要另一个 真的示例,但是我想添加一个简单易读的示例,并且不需要特殊处理任何事情。相反,我的代码依次对每个10的幂进行处理,在每个10之内,可以进入“债务”,以处理减法符号。

// For each power of 10, we break down the number
// and build up the roman numeral characters
function convertToRoman(num) {
let roman = [];
[roman, num] = convertPowerOfTen(roman, num, 1000, "M");
[roman, num] = convertPowerOfTen(roman, num, 100, "C", "D");
[roman, num] = convertPowerOfTen(roman, num, 10, "X", "L");
[roman, num] = convertPowerOfTen(roman, num, 1, "I", "V");
return roman.join("");
}


function convertPowerOfTen(roman, num, multiplier, unitChar, fiveChar) {
// Handle multiple of 5, possibly going into "debt"
if (num >= 4 * multiplier) {
roman.push(fiveChar);
num -= 5 * multiplier;
}
// If in debt, insert unit character before the last one
if (num <= -1) {
roman.splice(-1, 0, unitChar)
num += multiplier;
}
// Insert as many unit characters as needed
while (num >= multiplier * 0.9) {
roman.push(unitChar);
num -= multiplier;
}
return [roman, num];
}

作为一个菜鸟,这就是我对这个问题的回答:

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