您好我正在尝试使用javascript将罗马数字转换为阿拉伯语。我写了一个代码,但它失败了。 我想遵循的规则是:
如果较大的数字在较小的数字之前,则加法,如果较小的数字在较大的数字之前,则减去。
除此之外我还有其他一些规则,比如'D','L'和'V'根本不能重复,'M'只能重复两次(不知道如何实现这个,可以我使用正则表达式以及如何使用?)
代码:
function romanToArabic(roman){
if(roman == null)
return -1;
var value;
for(var i=0;i<roman.length;i++){
current = char_to_int(roman.charAt(i));
next = char_to_int(roman.charAt(i+1));
console.log("Current",current);
console.log("Next",next);
if(current >= next){
value = current + next;
console.log(value);
}
else {
console.log(value);
value = next - current;
}
}
return value;
}
function char_to_int(character) {
switch(character){
case 'I': return 1;
case 'V': return 5;
case 'X': return 10;
case 'L': return 50;
case 'C': return 100;
case 'D': return 500;
case 'M': return 1000;
default: return -1;
}
}
console.log(romanToArabic('IIX'));
有人可以帮忙吗?会很感激的!
添加了屏幕截图:
答案 0 :(得分:1)
问题是您的代码只会减去与一个字符对应的值,而在IIX
中您需要减去两次(尽管数字8的那种表示非常不同寻常 - 8通常表示为VIII
)。
解决方案是在符号相同时继续收集一个单独的总和,这样在读完前两个“I”后,你有两个单独的总和:
然后当您遇到“X”并检测到需要减法时,首先撤消已经为总计进行的添加,然后使用您为“I”收集的值执行减法:
在此之后,您将从“X”的重置值开始:
以下是适合您的代码:
function romanToArabic(roman){
if(roman == null)
return -1;
var totalValue = 0,
value = 0, // Initialise!
prev = 0;
for(var i=0;i<roman.length;i++){
var current = char_to_int(roman.charAt(i));
if (current > prev) {
// Undo the addition that was done, turn it into subtraction
totalValue -= 2 * value;
}
if (current !== prev) { // Different symbol?
value = 0; // reset the sum for the new symbol
}
value += current; // keep adding same symbols
totalValue += current;
prev = current;
}
return totalValue;
}
function char_to_int(character) {
switch(character){
case 'I': return 1;
case 'V': return 5;
case 'X': return 10;
case 'L': return 50;
case 'C': return 100;
case 'D': return 500;
case 'M': return 1000;
default: return -1;
}
}
console.log(romanToArabic('IIX'));
关于将连续“I”的数量限制为最多两个,“D”最多为一个的额外问题,......您可以在函数开头使用正则表达式测试:
if (/III|XXX|CCC|MMM|VV|LL|DD|[^IVXLCDM]/.test(roman))
return -1;
您可以添加由|
分隔的其他无效子序列。例如,如果您不希望“I”直接出现在“L”,“C”,“D”或“M”之前,则扩展为:
if (/III|XXX|CCC|MMM|VV|LL|DD|[^IVXLCDM]|I[LCDM]/.test(roman))
return -1;
答案 1 :(得分:0)
const romans = { '我':1, 'V':5 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000 };
// MXMIV
function roman2arabic(nums){
let sum = 0;
const numsArr = nums.split('');
const isSimpleRoman = (num) => num in romans;
const arabicCompare = (current, prev) => romans[current] < romans[prev];
const orderNums = (acc, current) => {
const prev = acc[acc.length - 1] || null;
const arabCurrent = romans[current];
if (prev && isSimpleRoman(prev) && arabicCompare(current, prev)) {
sum -= arabCurrent;
acc.pop() && acc.push(current + prev);
} else {
sum += arabCurrent;
acc.push(current);
}
return acc;
};
return numsArr.reduceRight(orderNums, []) && sum;
}
答案 2 :(得分:0)
const romans = { '我':1, 'V':5 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000 };
function roman2arabicRecursion(nums){
const numsArr = nums.split('');
const recursion = (arr, index, sum) => {
const current = arr[index];
const prev = arr[index + 1] || null;
if(prev && romans[current] < romans[prev]){
sum -= romans[current];
} else {
sum += romans[current];
}
if(index === 0) return sum;
return recursion(arr, index - 1, sum);
}
return recursion(numsArr, numsArr.length - 1, 0);
};
答案 3 :(得分:0)
对于那些可能需要翻译罗马数字而不是不规则减法表示法(例如,用“ IIX”代替“ VIII”表示8)的人,我可能建议我自己写,方法略短:
const test = ['XIV'/*14*/, 'MXMVI'/*1996*/, 'CII'/*102*/, 'CDI'/*401*/];
const roman2arabic = s => {
const map = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000};
return [...s].reduce((r,c,i,s) => map[s[i+1]] > map[c] ? r-map[c] : r+map[c], 0);
};
console.log(test.map(roman2arabic));
.as-console-wrapper {min-height: 100%}
但是,可以对其进行修改以遵循非常规逻辑:
const test = ['IIV'/*3*/,'XXMMII'/*1982*/, 'IIIXV'/*12*/, 'XII'/*conventional 12*/];
const roman2arabic = s => {
const map = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000};
return [...s]
.reduceRight(({sum,order},c,i,s) =>
Object.keys(map).indexOf(c) < order ?
{sum: sum-map[c], order} :
{sum: sum+map[c], order: Object.keys(map).indexOf(c)},
{sum:0,order:Object.keys(map).indexOf(s[s.length-1])})
.sum;
};
console.log(test.map(roman2arabic));
.as-console-wrapper {min-height: 100%}
答案 4 :(得分:0)
也可以使用 || 运算符代替 ??
const toArabic = (romanNumber) => {
const map = {
M: 1000,
D: 500,
C: 100,
L: 50,
X: 10,
V: 5,
I: 1,
};
const nums = romanNumber.split('');
let result = 0;
for (let i = 0; i < nums.length; i += 1) {
const first = map[nums[i]];
const second = map[nums[i + 1]] ?? 0;
if (first < second) {
result += second - first;
i += 1;
} else {
result += first;
}
}
return result;
};
console.log(toArabic('CMXI')); // 911
console.log(toArabic('MXXIV')); // 1024