You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

罗马数字转换器返回undefined值问题求助

罗马数字转换器返回undefined值问题求助

我仔细看了你的代码,发现你遇到的undefined问题主要是两个核心原因:罗马数字映射列表的结构设计不对,还有数组操作的逻辑绕了弯路且有误,咱们一步步来调整修复:

问题1:lettersList的结构错误

你现在把每一位的罗马数字放在了单独的对象里(比如{0: ['', 'I', ...]}),但实际上你需要的是一个二维数组——外层数组的索引对应位数(0=个位,1=十位,2=百位,3=千位),内层数组的索引对应数字(0-9),直接返回对应的罗马字符。

原来的结构中,当你用lettersList[i][deletedItem[0]]时,lettersList[i]是一个对象,而对象里并没有deletedItem[0](比如数字3)这个键,所以自然返回undefined。

修正后的lettersList应该是这样:

const lettersList = [
  ['', 'I','II','III','IV','V', 'VI', 'VII', 'VIII', 'IX'], // 个位(索引0)
  ['', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'], // 十位(索引1),开头加空字符串对应数字0的情况
  ['', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM'], // 百位(索引2)
  ['', 'M', 'MM', 'MMM'] // 千位(索引3)
]

问题2:数组操作逻辑冗余且错误

你用splice反复删除插入元素的思路太绕了,其实可以更简单:直接遍历拆分后的数字位,把每一位对应的罗马字符收集到新数组里,最后反转拼接成正确顺序即可。

原来的代码中,inputList.splice(i, 1,)这种写法本身就有语法问题,而且反复修改原数组很容易导致索引混乱。

修复后的完整代码

<!-- 假设你的HTML基础结构如下 -->
<input type="number" id="number" placeholder="输入1-3999的数字">
<button id="convert-btn">转换</button>
<div id="output" hidden></div>

<script>
const output = document.getElementById("output");
const number = document.getElementById('number');
const convertBtn = document.getElementById('convert-btn');

const lettersList = [
  ['', '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']
];

const makeNum = (input) => {
  output.removeAttribute("hidden");
  const inputValue = parseInt(input.value); // 转成数字,避免字符串比较的潜在问题
  let result = [];

  if (inputValue > 3999) {
    output.innerHTML = '<p>Please enter a number less than or equal to 3999</p>';
    return; // 提前退出,避免无效逻辑执行
  } else if (inputValue < 1 || isNaN(inputValue)) { // 新增非数字输入的判断
    output.innerHTML = '<p>Please enter a number greater than or equal to 1 </p>';
    return;
  }

  // 拆分数字的每一位,比如123拆成3(个位)、2(十位)、1(百位)
  let num = inputValue;
  let digitIndex = 0; // 对应lettersList的索引(0=个位)
  while (num > 0) {
    const digit = num % 10; // 取当前个位数字
    result.push(lettersList[digitIndex][digit]); // 收集对应罗马字符
    num = Math.floor(num / 10); // 去掉已处理的个位数字
    digitIndex++;
  }

  // 反转数组并拼接,得到正确顺序的罗马数字
  const romanNumeral = result.reverse().join('');
  output.innerHTML = `<p>${romanNumeral}</p>`;
};

convertBtn.addEventListener("click", () => {
  makeNum(number);
});
</script>

关键调整说明

  1. 先把输入值转成数字parseInt(input.value),避免字符串和数字比较的潜在bug(比如字符串"10000"和数字3999比较会出问题)。
  2. 用while循环拆分每一位数字,比操作字符串数组更直观,也避免了索引混乱。
  3. 收集每一位对应的罗马字符后,反转数组再拼接,就能得到正确顺序的罗马数字。
  4. 增加了isNaN判断,处理用户输入非数字的情况。

现在你测试一下,输入123应该得到CXXIII,输入3999得到MMMCMXCIX,输入4得到IV,都能正常工作啦~

备注:内容来源于stack exchange,提问作者conmanh01

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.20 07:58:16