【问题标题】:Haskell function to convert Int to alpha numerotation [closed]Haskell 函数将 Int 转换为 alpha numerotation [关闭]
【发布时间】:2019-08-30 16:01:59
【问题描述】:

我正在尝试编写一个 Haskell 函数来将整数转换为带有字母数字循环的字符串。

通过字母数字,我的意思是与此转换匹配的数字:

1 -> A
2 -> B
3 -> C
..
25 -> Y
26 -> Z
27 -> AA
28 -> AB
29 -> AC
..

我发现这个function 可以将十进制数字转换为罗马数字,并尝试对其进行修改以做我想做的事情。但我没有设法得到正确的结果。问题是在字母计数中,“A”在用作单位或倍数时具有不同的“权重”(它可以是 1 或 0)。

你知道如何获得正确的转换吗?

【问题讨论】:

  • 您正在转换为基数 26,其中数字是字母 A-Z。
  • 什么,不为零?只有正面?
  • 是的,这个功能是重现Office计算列中使用的数字,LaTeX/HTML章节编号(counter(subsection,upper-alpha)
  • 这很容易出错,因为它非常类似于转换为base 26,但在第一个字母上有细微的差别。在基数 26 中,第一个数字的范围从 125,而所有其他数字的范围从 025。相反,在上面的枚举中,所有字母的范围从AZ
  • @chi 你说得对,我没有意识到这个微妙之处。我会弄错的。

标签: haskell number-formatting numeric


【解决方案1】:

使用模运算非常容易。我们将编写一个以相反顺序返回字母的函数;之后我们可以在顶层修复它。基本思想是反复除以 26。所以:

rawCellName :: Int -> String
rawCellName x | x <= 0 = []
rawCellName x = toEnum (fromEnum 'A' + r) : rawCellName q where
    (q, r) = (x-1) `quotRem` 26

然后在顶层我们只是修复 API 的奇怪之处:

cellName :: Int -> String
cellName = reverse . rawCellName

在 ghci 中尝试一下:

> map cellName [1..5]
["A","B","C","D","E"]
> map cellName [25..30]
["Y","Z","AA","AB","AC","AD"]

【讨论】:

    【解决方案2】:

    这里我们可以先将数字转化为数字序列,每次除以26,然后取模:

    import Data.List(unfoldr)
    
    toColumnName :: Int -> String
    toColumnName = reverse . fmap (toEnum . (64+)) . unfoldr f
        where f 0 = Nothing
              f n = Just ((mod (n-1) 26)+1, div (n-1) 26)

    或更短:

    import Data.List(unfoldr)
    import Data.Tuple(swap)
    
    toColumnName :: Int -> String
    toColumnName = reverse . fmap (toEnum . (65+)) . unfoldr f
        where f 0 = Nothing
              f n = Just (swap (divMod (n-1) 26))

    例如:

    Prelude Data.List> map toColumnName [1..100]
    ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","AA","AB","AC","AD","AE","AF","AG","AH","AI","AJ","AK","AL","AM","AN","AO","AP","AQ","AR","AS","AT","AU","AV","AW","AX","AY","AZ","BA","BB","BC","BD","BE","BF","BG","BH","BI","BJ","BK","BL","BM","BN","BO","BP","BQ","BR","BS","BT","BU","BV","BW","BX","BY","BZ","CA","CB","CC","CD","CE","CF","CG","CH","CI","CJ","CK","CL","CM","CN","CO","CP","CQ","CR","CS","CT","CU","CV"]
    

    【讨论】:

      猜你喜欢
      • 2018-05-11
      • 2011-02-16
      • 2012-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-05
      • 2014-11-08
      相关资源
      最近更新 更多