【问题标题】:Octave/MATLAB Function to Convert Roman Numeral Into Decimal NumberOctave/MATLAB 函数将罗马数字转换为十进制数
【发布时间】:2018-05-26 03:19:11
【问题描述】:

我正在尝试在 Octave 中编写一个函数来将罗马数字转换为十进制数字。

我目前有两个主要问题:

1) 它只适用于长度不超过 6 个字母的罗马数字

2) 只有当每个字母都小于前一个时,答案才是正确的。即它不会正确计算 (IV) 为 4,而是错误地计算为 6。

我需要以某种方式解决这两个问题。我强烈怀疑我解决问题的方法是错误的,并且有一种更有效的方法可以做到这一点。

无论如何,如果您对问题感兴趣和/或您知道解决此问题的好方法,我们非常感谢您提供任何帮助。

function roman2num(s)

  decimal = [1000, 500, 100, 50, 10, 5, 1];
  roman = ["M", "D", "C", "L", "X", "V", "I"];

  num = 0;

  for i = 1:7
    if strcmp(s(1), roman(i))
      num += decimal(i);
      break 
    end
  end

      if length(s) >= 2
      for i = 1:7
        if strcmp(s(2), roman(i))
          num += decimal(i);
          break 
        end
      end
   end

    if length(s) >= 3
      for i = 1:7
        if strcmp(s(3), roman(i))
          num += decimal(i);
          break 
        end
      end
   end

    if length(s) >= 4
      for i = 1:7
        if strcmp(s(4), roman(i))
          num += decimal(i);
          break 
        end
      end
   end

    if length(s) >= 5
      for i = 1:7
        if strcmp(s(5), roman(i))
          num += decimal(i);
          break 
        end
      end
   end

    if length(s) >= 6
      for i = 1:7
        if strcmp(s(6), roman(i))
          num += decimal(i);
          break 
        end
      end
   end

  num

end

【问题讨论】:

    标签: matlab loops if-statement octave roman-numerals


    【解决方案1】:

    据我所知,您需要担心的唯一规则是确定该字母是构成“加”还是“减”操作。对于某个字母,只有在右边第一个不相等的字母代表更大的值时,我们才减去它。

    例如在'IIV' 中,I 右侧的第一个不相等的字母是 V,因此我们为 V 减去 2 并添加 5,因为它的右侧没有字母。

    在 MATLAB 中实现此规则相当简单。

    function num = roman2num(s)
        decimal = [1000, 500, 100, 50, 10, 5, 1];
        roman = ['M', 'D', 'C', 'L', 'X', 'V', 'I'];
        tokens = arrayfun(@(x) decimal(find(roman==x,1)), char(s));
        num = tokens(end);
        for idx = 1:numel(tokens)-1
            val = tokens(idx);
            ridx = find(tokens(idx+1:end) ~= val, 1);
            if ~isempty(ridx) && tokens(ridx + idx) > val
                num = num - val;
            else
                num = num + val;
            end
        end
    

    我使用 1 到 3333 之间的所有数字进行了测试。

    【讨论】:

    • 您的解决方案看起来很简洁。感谢您抽出宝贵的时间。我想我理解程序直到第 8 行和第 9 行创建和使用变量 ridx。我想我只是不太了解 find 功能。有什么进一步的解释可以给我吗?
    • @rustybandit 当然可以。第一个参数tokens(idx+1:end) ~= val 是一个包含1 的布尔数组,其中tokens(idx+1:end) 等于val0find 返回此数组的第一个非零条目的索引。由于我在将令牌数组传递给find 之前截断了它,因此我需要将idx 添加到ridx 以获取相对于令牌开头的索引。这导致ridx+idxidx 右侧第一个条目的索引,它不等于tokens(idx)。或者如果不存在这样的条目,那么ridx 将为空。
    猜你喜欢
    • 2017-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-09
    • 2011-10-25
    相关资源
    最近更新 更多