我正在构建一个基本转换器。到目前为止,这是我的代码:
def num_to_s(num, base)
remainders = [num]
while base <= num
num /= base #divide initial value of num
remainders << num #shovel results into array to map over for remainders
end
return remainders.map{|i| result = i % base}.reverse.to_s #map for remainders and shovel to new array
puts num_to_s(40002, 16)
end
现在是时候考虑字母替换数字的超过10的基数。 (练习的)指示建议使用哈希。这是我的哈希:
conversion = {10 => 'A', 11 => 'B', 12 => 'C', 13 => 'D', 14 => 'E', 15 => 'F',}
现在的问题是,如何将其合并以便修改数组?我试过了:
return remainders.map{|i| result = i % base}.map{|i| [i, i]}.flatten.merge(conversion).reverse.to_s
尝试将'remainingders'数组转换为哈希并合并它们,以便'conversion'中的值覆盖'remainingders'中的值,但是我得到'奇怪的Hash列表'错误。经过一些研究后,似乎是由于我正在运行的Ruby版本(1.8.7),并且无法更新。我也尝试将数组转换为返回之外的哈希:
Hashes = Hash[remainders.each {|i, i| [i, i]}].merge(conversion)
我得到一个'动态常量赋值'错误。我尝试了很多不同的方法来做到这一点......哈希甚至可以用来修改数组吗?我也在想也许我可以通过在枚举器中使用条件语句来实现这一点(每个?map?)但是却无法完成这项工作。 CAN可以在枚举器中放置一个条件吗?
答案 0 :(得分:1)
除了问题,您可以使用Fixnum#to_s(base)来转换基础。
255.to_s(16) # 'ff'
答案 1 :(得分:1)
我会做一个
def get_symbol_in_base(blah)
if blah < 10
return blah
else
return (blah - 10 + 65).chr
end
end
然后执行以下操作:
remainders << get_symbol_in_base(num)
return remainders.reverse.to_s
答案 2 :(得分:1)
是的,您可以使用哈希:
def digit_hash(base)
digit = {}
(0...[10,base].min).each { |i| digit.update({ i=>i.to_s }) }
if base > 10
s = ('A'.ord-1).chr
(10...base).each { |i| digit.update({ i=>s=s.next }) }
end
digit
end
digit_hash(40)
#=> { 0=>"0", 1=>"1", 2=>"2", 3=>"3", 4=>"4",
# 5=>"5", 6=>"6", 7=>"7", 8=>"8", 9=>"9",
# 10=>"A", 11=>"B", 12=>"C", ..., 34=>"Y", 35=>"Z",
# 36=>"AA", 37=>"AB", 38=>"AC", 39=>"AD" }
在&#39; Z&#39;之后显示数字时出现问题。例如,假设基数为65.那么人们就不知道&#34; ABC&#34;是10-11-12,37-12或10-64。这个细节我们不用担心。
对于多样性,我已经完成了从高到低的基本转换,就像基地10的纸和笔一样:
def num_to_s(num, base)
digit = digit_hash(base)
str = ''
fac = base**((0..Float::INFINITY).find { |i| base**i > num } - 1)
until fac.zero?
d = num/fac
str << digit[d]
num -= d*fac
fac /= base
end
str
end
让我们试一试:
num_to_s(134562,10) #=> "134562"
num_to_s(134562, 2) #=> "100000110110100010"
num_to_s(134562, 8) #=> "406642"
num_to_s(134562,16) #=> "20DA2"
num_to_s(134562,36) #=> "2VTU"
让我们检查最后一个:
digit_inv = digit_hash(36).invert
digit_inv["2"] #=> 2
digit_inv["V"] #=> 31
digit_inv["T"] #=> 29
digit_inv["U"] #=> 30
所以
36*36*36*digit_inv["2"] + 36*36*digit_inv["V"] +
36*digit_inv["T"] + digit_inv["U"]
#=> 36*36*36*2 + 36*36*31 + 36*29 + 30
#=> 134562
表达式:
(0..Float::INFINITY).find { |i| base**i > num }
计算i
的最小整数base**i > num
。例如,假设
base = 10
num = 12345
然后发现i
等于5
(10**5 = 100_000
)。然后我们将base
提高到这个数字,减去一个得到初始因子:
fac = base**(5-1) #=> 10000
然后第一个(基数为10)的数字是
d = num/fac #=> 1
剩下的是
num -= d*fac #=> 12345 - 1*10000 => 2345
,下一个数字的因素是:
fac /= base #=> 10000/10 => 1000
我从最初的答案做了几处修改,以1.87-friedly(我删除了Enumerator#with_object
和Integer#times
),但我还没有用1.8.7进行测试,因为我没有安装该版本。如果有任何问题,请告诉我。