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

IT技术 javascript roman-numerals
2021-02-06 23:31:14

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

function romanNumeralGenerator (int) {

}

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

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

警告:仅支持 1 到 3999 之间的数字

6个回答

我使用谷歌在这个博客上找到了一个很好的:

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;
}
@tukusejssirs 幸运的是,罗马数字可以使用多年,否则会有大于 1000 的数字。但很高兴知道!
2021-03-20 23:31:14
提醒:这应该更好地返回NaN或抛出而不是false该帖子中讨论的返回
2021-03-21 23:31:14
我刚刚发现可以使用此函数的最大数字是715799999999(715,799,999,999)。较大的数字要么不返回任何内容,要么(对于非常大的数字)它会输出RangeError: Invalid array length错误。否则,它可以完美运行。谢谢!
2021-03-30 23:31:14
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

查看演示

我不能举一个不工作的例子,因为顺序是依赖于实现的。相反,请将规范的哪一部分链接给我,以确保它将以所需的顺序进行迭代。哦,你不能
2021-03-14 23:31:14
@jaggedsoft这里就是为了在某些浏览器改变了一个例子:for (let i in { '2': 2, '1': 1 }) console.log(i);此外,即使您对其进行了测试,也不意味着它始终有效。可能存在浏览器出于性能原因或任何原因更改顺序的情况。您只能确定,如果您知道您支持并希望将来支持的每个浏览器版本的源代码。
2021-03-23 23:31:14
对象没有顺序!您应该使用数组并避免for...in.
2021-04-01 23:31:14
我不是在谈论性能。我是说迭代顺序没有保证,所以结果可能完全错误。
2021-04-01 23:31:14
这很好,解析这里发生的事情在精神上似乎更容易。从最大的数开始,继续从查找表中减去,只要余数大于查找值就追加。
2021-04-07 23:31:14

我不明白为什么每个人的解决方案都这么长并且使用多个 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;
}
我想我终于明白了这个解决方案。添加 'if (num===0){return str}' 会使循环更少吗?您可以将它放在循环的末尾并删除“返回 str”。
2021-03-14 23:31:14
是的@kite,很好地发现了!它会减少循环,但是,考虑到我们只循环了 13 个项目,它不会有太大区别:)
2021-03-18 23:31:14

我开发了下面的递归解决方案。该函数返回一个字母,然后调用自身返回下一个字母。它一直这样做,直到传递给函数的数字是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]);
    }
  }
}
我真的很喜欢你的解决方案。易于阅读、理解且非常简单。好的!
2021-03-24 23:31:14
迄今为止最好的解决方案。
2021-04-01 23:31:14
发生了太多重复,这是不必要的。
2021-04-02 23:31:14

这些函数将任何正整数转换为其等效的罗马数字字符串;和任何罗马数字到它的数字。

数字到罗马数字:

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