使用javascript将罗马数字转换为阿拉伯语

时间:2018-02-23 10:49:20

标签: javascript

您好我正在尝试使用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'));

有人可以帮忙吗?会很感激的!

添加了屏幕截图:

enter image description here

enter image description here

5 个答案:

答案 0 :(得分:1)

问题是您的代码只会减去与一个字符对应的值,而在IIX中您需要减去两次(尽管数字8的那种表示非常不同寻常 - 8通常表示为VIII)。

解决方案是在符号相同时继续收集一个单独的总和,这样在读完前两个“I”后,你有两个单独的总和:

  • 总计:2
  • 所有“我”的价值:2

然后当您遇到“X”并检测到需要减法时,首先撤消已经为总计进行的添加,然后使用您为“I”收集的值执行减法:

  • 总计:-2

在此之后,您将从“X”的重置值开始:

  • 总计:10 + -2 = 8
  • 所有“X”的值:10

以下是适合您的代码:

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