使用ruby生成表示数字的字母?

使用ruby生成表示数字的字母?,ruby,math,numerical,Ruby,Math,Numerical,我想生成一系列字母,即“a”、“DE”、“GJE”等,它们对应于一个数字。前26个非常简单,因此3个返回“C”,26个返回“Z”,27个返回“AA”,28个返回“AB”,依此类推 我不太清楚的是如何做到这一点,这样它就可以处理传入的任何数字。所以,如果我通过4123,我应该会得到一些3个字母的组合,因为(26*26*26)最多允许+17000个组合 有什么建议吗?使用找到的基本转换方法。我还更改了它,因为我们在这个编号系统中没有“0”。最终案例已得到解决 class Numeric Alph

我想生成一系列字母,即“a”、“DE”、“GJE”等,它们对应于一个数字。前26个非常简单,因此3个返回“C”,26个返回“Z”,27个返回“AA”,28个返回“AB”,依此类推

我不太清楚的是如何做到这一点,这样它就可以处理传入的任何数字。所以,如果我通过4123,我应该会得到一些3个字母的组合,因为(26*26*26)最多允许+17000个组合


有什么建议吗?

使用找到的基本转换方法。我还更改了它,因为我们在这个编号系统中没有“0”。最终案例已得到解决

class Numeric
  Alph = ("a".."z").to_a
  def alph
    s, q = "", self
    (q, r = (q - 1).divmod(26)); s.prepend(Alph[r]) until q.zero?
    s
  end
end

3.alph
# => "c"
26.alph
# => "z"
27.alph
# => "aa"
4123.alph
# => "fbo"
def baseAZ(num)
  # temp variable for converting base
  temp = num

  # the base 26 (az) number
  az = ''

  while temp > 0

    # get the remainder and convert to a letter
    num26 = temp % 26
    temp /= 26

    # offset for lack of "0"
    temp -= 1 if num26 == 0

    az = (num26).to_s(26).tr('0-9a-p', 'ZA-Y') + az
  end

  return az
end
irb I/O:

>> baseAZ(1)
=> "A"
>> baseAZ(26^2 + 1)
=> "Y"
>> baseAZ(26*26 + 1)
=> "ZA"
>> baseAZ(26*26*26 + 1)
=> "YZA"
>> baseAZ(26*26*26 + 26*26 + 1)
=> "ZZA"

字符串确实有一个
succ
方法,因此它们可以在一定范围内使用。“Z”的后继者恰好是“AA”,因此这是可行的:

h = {}
('A'..'ZZZ').each_with_index{|w, i| h[i+1] = w } 
p h[27] #=> "AA"

根据sawa的回答,我想要一种独立工作的方法,尽管是递归的,以实现期望的结果:

def num_to_col(num)
  raise("invalid value #{num} for num") unless num > 0
  result, remainder = num.divmod(26)
  if remainder == 0
    result -= 1
    remainder = 26
  end
  final_letter = ('a'..'z').to_a[remainder-1]
  result > 0 ? previous_letters = num_to_col(result) : previous_letters = ''
  "#{previous_letters}#{final_letter}".upcase
end

对@sawa的调整是Ruby 2.0的原始答案,因为我无法让他按原样工作:

class Numeric
  Alpha26 = ("a".."z").to_a
  def to_s26
    return "" if self < 1
    s, q = "", self
    loop do
      q, r = (q - 1).divmod(26)
      s.prepend(Alpha26[r]) 
      break if q.zero?
    end
    s
  end
end
用法:

1234567890.to_s26 
# => "cywoqvj"

"cywoqvj".to_i26  
# => 1234567890

1234567890.to_s26.to_i26
# => 1234567890

"".to_i26
# => 0

0.to_s26
# => ""

我喜欢这个答案:

下面是一个简短的基于性能递归的解决方案
类数值
#“z”被放置在数组的开头,因为26%26是0而不是26
Alph=['z']+(“a“.“y”)。到a
def to_alph
#如果self为0或负值,则返回一个空字符串。
#这还用于结束to_alph调用的递归链
#因此,不要将此替换为引发错误或返回任何其他内容
如果self<1,则返回“”
#(否则)返回两个串联字符串:
#右侧是用于自我模块26的字母
#左侧由以下部分组成:
#  1. 减1,因为这不是基于零的编号系统。
#因此,整数(26,52…)应返回一位数字“z”
#而不是两位数字“aa”或“ba”。
#  2. 除以26,然后打电话给阿尔普。
#对于最后一个字符串的每个数字,它都会递归重复,
#再加一次,它将返回“”以结束递归链。
返回((self-1)/26)。到_alph+alph[self%26]
结束
结束

通过从字母表的序号中减去96,可以得到字符在字母表中的数字位置,如下所示:

"a".ord - 96
=> 1

"z".ord - 96
=> 26
(1 + 96).chr
=> "a"

(26 + 96).chr
=> "z"
您还可以通过添加96,通过其数字位置获取字母字符,如下所示:

"a".ord - 96
=> 1

"z".ord - 96
=> 26
(1 + 96).chr
=> "a"

(26 + 96).chr
=> "z"


这基本上是一个基数为26的数字(但基数中没有数字)@SergioTulentsev-事实证明,这个问题更复杂。我认为导致麻烦的关键特征是
A
在某些情况下意味着“0”(作为“一”位),但
A
在其他情况下意味着“1”(作为“十/二十六”位。有趣的是,微软的某个人必须解决这个问题;)我遗漏了一些东西。为什么“A”是特别的?A=1*1=1,AA=1*26+1*1=27。@glennmcdonald“A”并不特别。“A”始终对应于“1”。特别的是跳过了“0”。想象一下十进制,向上计数,跳过“0”:1,2,…,8,9,11,12,…,18,19,21,22,…,98,99,111,112。。。现在,如果你用七进制(以27为基数)而不是十进制,你就得到了序列。哦,对了。在Base26中可能更容易实现,因为它的值为0。不清楚零的东西是需求还是想象解决方案的产物。我相信这是目前为止唯一正确的解决方案,尽管我不确定到底发生了什么……太棒了。我还从中获得了新的见解。计算总组合的方法如下!(26^(n-1))。我不是数学家,所以这可能是完全虚构的,但这会给你(26^3)+(26^2)+(26^1)表示三个字母,和(26^2)+(26^1)表示两个字母,等等。在rails应用程序中使用这个的最佳方式是什么?要在lib目录中包含该类并需要它?@JeremyRichards将其放在
config/initializers/numeric.rb
fileInsightful中,注意这个数字系统“缺少零”,尽管事后看来很明显。我发现OP希望转换为,通过该关键字搜索,似乎没有基于音译的转换算法。我认为一个简单的基于音译的算法是不可能的,因为在无零系统中总会有一个单位数符号,必须映射到零系统中的一个两位数符号。使用这种方法,你不能当场随机计算某个数字的字符串,但是你必须通过所有的数字来达到目标数字。出于性能原因,Sawa的答案要好得多,但是如果你将此响应作为一种快速而肮脏的方法,那么下面一行就可以做到:x=27;('A'..'ZZZ')。如果(i+1)=x;i+1},则减少(0){i,l | break(l)}实际上这比@Sawa快(根据结果是17倍),前提是哈希被重复使用。这样做的代价是使用更多的内存。这个答案是为一个固定的范围预先生成散列,并且只在需要时引用它。我的答案是当场生成任意序列的。他们无法比较,这是一个很好的发现。我已经更新了我的答案,因此小于1的任何内容都将返回空字符串。请注意,字符串#to_i26方法会修改它在下套管时调用的字符串。要改变这一点,请改变
downcase
string=downcase
char=self[-i]
char=string[-i]
这是一个很好的解决方案。根据这个问题,这不太管用。例如,27应该返回“AA”,这个返回“BB”。这个答案不起作用。问题是27应该返回“AA”,这个方法返回“BB”对不起-这个答案适用于我的情况,我不关心生成的确切字母,但我同意这是错误的。我最终使用了这个,因为我需要一个零
(1 + 96).chr
=> "a"

(26 + 96).chr
=> "z"