如何将整数转换为罗马数字?
function romanNumeralGenerator (int) {
}
例如,请参阅以下示例输入和输出:
1 = "I"
5 = "V"
10 = "X"
20 = "XX"
3999 = "MMMCMXCIX"
警告:仅支持 1 到 3999 之间的数字
如何将整数转换为罗马数字?
function romanNumeralGenerator (int) {
}
例如,请参阅以下示例输入和输出:
1 = "I"
5 = "V"
10 = "X"
20 = "XX"
3999 = "MMMCMXCIX"
警告:仅支持 1 到 3999 之间的数字
我使用谷歌在这个博客上找到了一个不错的博客:
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;
}
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
我不明白为什么每个人的解决方案都这么长并且使用多个 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;
}
我开发了下面的递归解决方案。该函数返回一个字母,然后调用自身返回下一个字母。它会一直这样做,直到传递给函数的数字是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]);
}
}
}
这些函数将任何正整数转换为其等效的罗马数字字符串;和任何罗马数字到它的数字。
数字到罗马数字:
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;
};
我个人认为最简洁的方法(绝不是最快的)是递归。
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,但可以通过遵循模式轻松扩展。
此版本不需要像其他版本那样针对边缘情况进行任何硬编码逻辑4(IV),9(IX),40(XL),900(CM), etc.
。
我已经针对 1-3999 的数据集测试了这段代码,它可以工作。
TLDR;
这也意味着此解决方案可以处理大于最大罗马刻度 (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);
我知道这是一个老问题,但我为这个解决方案感到非常自豪:) 它只处理小于 1000 的数字,但可以通过添加到“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;
}
<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">
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找到许多其他建议
循环可能更优雅,但我发现它们很难阅读。想出了一个或多或少的硬编码版本,看起来很容易。只要你理解了第一行,剩下的就很容易了。
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;
}
此函数将任何小于 3,999,999 的数字转换为罗马数字。请注意,大于 3999 的数字将位于text-decoration
设置为的标签内,当数字大于 3999 时overline
,这将添加overline
x1000 的正确表示。
四百万(4,000,000)将是带有两个overline
s 的 IV,因此,您需要使用一些技巧来表示它,可能是DIV
带有s 的一个border-top
,或者带有这两个overline
s 的一些背景图像......每个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;
}
如果您想用更多符号转换一个大数字,也许这个算法会有所帮助。
符号的唯一前提是它必须是奇数并且遵循相同的规则 (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>
这是递归的解决方案,看起来很简单:
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
在测试了这篇文章中的一些实现之后,我创建了一个新的优化的,以便更快地执行。与其他执行时间相比,执行时间确实很低,但显然代码更丑:)。使用具有所有可能性的索引数组可能会更快。以防万一它帮助某人。
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 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];
然后我添加了一个扫描罗马元素的循环,将 NUM 中包含的最大元素添加到 RESULT,然后我们减少相同数量的 NUM。
就像我们将 NUM 的一部分映射为罗马数字,然后我们将其减少相同的数量。
for (var x = 0; x < rom.length; x++) {
while (num >= ara[x]) {
result += rom[x];
num -= ara[x];
}
}
return result;
}
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));
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 };
function toRoman(number = 0) {
return Object.keys(_roman).reduce((acc, key) => {
while (number >= _roman[key]) {
acc += key;
number -= _roman[key];
}
return acc;
}, '');
}
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
我还没有看到这个帖子,所以这是一个仅使用字符串操作的有趣解决方案:
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))
如果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
这是一个正则表达式解决方案:
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;
}
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>
我刚在 freecodecamp 做这个。它可以很容易地扩展。
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;
}
此解决方案仅运行一个循环,并且具有将数字映射到罗马字母的最小对象
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
有几种方法可以做到这一点。我个人更喜欢使用对象并遍历键值对:
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;
}
仍然为此感到自豪:) 它在 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);
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 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);
此功能适用于每个数字中的不同字符集。要添加另一个数字,请将罗马数字字符串添加到第 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>
这仅适用于所有需要罗马数字 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;
}
如果只是出于显示目的,请使用标准 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. -->
/*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
递归,转换前加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));
我的解决方案将数字分解为一个字符串数组,根据每个元素相对于数组长度的位置向每个元素添加零,将带有零的新字符串转换为罗马数字,然后将它们重新连接在一起。这仅适用于最多 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;
}
我觉得我的解决方案更具可读性和易于理解。
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;
};
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 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]);
}
}
}
这是我第一次真正陷入 freecodecamp 的困境。我在这里仔细阅读了一些解决方案,并对它们的不同之处感到惊讶。这就是最终为我工作的东西。
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 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)
我真的很喜欢 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));
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;
}
};
很好的回应。您可以通过编程方式完成此操作,而无需过多地对值进行硬编码。只是你的代码会更长一点。
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
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;
}
好吧,似乎我不是唯一一个在 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;
}
它似乎是一个限制,它只能转换高达 9 999 的数字。但事实是,从 10 000 起,应该在文字上方提供一行。而且我还没有解决。
希望这会帮助你。
字符串方式:(适用于 M chiffer 及以下)
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) {
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);
我也刚刚在 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 的数字提供正确的符号,但不要引用我的话。
我只是发布一个我制作的转换为罗马的函数,希望你喜欢
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
}
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 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 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 ''
}
这是一种无需遍历所有不同罗马数字及其对应数字的方法。它具有恒定的时间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;
}
这是我的解决方案:
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 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('');
}
自从提出这个问题以来,已经看过所有以前的 46 个“数字到罗马”的解决方案,只有一篇关于 kennebec 的反向罗马到数字的帖子,并且有几个问题:“数字”对象不能直接扩展,你需要使用原型。在这种情况下,原型设计也没有意义(如果有的话,字符串对象是更好的候选者)。其次,它不必要地复杂,另外还调用了 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>
如果有人需要,只需添加大数字
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;
}
只是连接 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);
}
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
}
我讨厌将每一种可能性都列在一个数组中(许多人选择用它来解决这个难题),所以我使用另一个函数来完成这项工作。这是我的解决方案:
//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++;
}
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))
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);
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 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);
这是我的“尽可能实用”的解决方案。
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 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;
}
婴儿的糖果。
首先,您必须将 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,那么您不需要在上面的对象中包含两个 romans 字符的属性。
然后构建一个函数来将基数转换为罗马数字:
// 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;
};
最后,如果您想进行逆运算,则构建一个将罗马转换为基数整数的函数:
// 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上试试。
虽然我的答案不如其他人那么高效,但我的重点更多是不要对基数进行硬编码,而是让程序找出其余部分。
例如......
而不是:
number = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1],
numeral = ['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('');
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))
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("");
}
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)
};
这是我的解决方案:
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;
}
它在 Chrome 60 中表现相当不错 - https://jsperf.com/num-to-roman
在此代码中,可以通过向 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;
}
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;
};
我是初学者,我看到的是 ))) 没有数组。当然,在函数中使用 itter + acc 会更好..刚刚通过 freeCodeCamp 的测试
我试图通过将阿拉伯数字数组映射到成对的罗马数字数组来做到这一点。讨厌的 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('');
}
此解决方案可用于小数字 (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();
它从 1 t0 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))
}
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;
}
这是我的;
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); }
可能是最简单的解决方案:
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在 CodeSignal 上的解决方案。
我从头开始为 freecodecamp 挑战编写了这个。我希望这会对某人有所帮助。
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));
使用此代码:
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;
}