Для 11 <= n <= 36
, Ruby имеет соглашение, которое позволяет целым числам быть выраженными в базе n
с 10 цифрами 0-9
и первыми n-10
символами алфавита. Именно по этой причине мы получаем следующие результаты: представление целых чисел
1270.to_s(36) #=> "za"
"za".to_i(36) #=> 1270
1270.to_s(37) #=> ArgumentError (invalid radix 37)
"za".to_i(37) #=> ArgumentError (invalid radix 37)
Ruby, однако, является всего лишь соглашением.
Я буду иметь дело только с отрицательные целые числа и будем называть их «числами». Отрицательные целые числа могут быть отрицаны, преобразованы в число другого основания, а затем это число отрицается.
Мы могли бы express чисел любого основания в виде массивов цифр, где каждое ди git выражается как основание 10 целое число. Например, мы могли бы написать:
46
в базе 10 как [4, 6]
za
в базе 36 как [36, 10]
- два -di git номер основания N как
[n, m]
, где n
и m
находятся между 0
и N-1
.
Мы можем написать метод для преобразования базы Число 10 в этом представлении массива:
def base10_to_base_n(n10, radix)
arr = []
while n10 > 0
n10, rem = n10.divmod(radix)
arr << rem
end
arr.reverse
end
base10_to_base_n(123, 10)
#=> [1, 2, 3]
base10_to_base_n(131, 2)
#=> [1, 0, 0, 0, 0, 0, 1, 1]
abase10_to_base_n(1234, 16)
#=> [4, 13, 2]
base10_to_base_n(9234, 99)
#=> [93, 27]
Обратите внимание, что в третьем примере:
4*(16**2) + 13*(16**1) + 2*(16**0) #=> 9234
Далее мы создайте метод, который делает обратное: преобразует число в заданной базе, описываемое как массив цифр (аргумент base_n
), в число из базы 10.
def base_n_to_base_10(base_n, radix)
pow = 1
arr = base_n.reverse
base_n.reverse.reduce do |n10, digit|
pow *= radix
n10 + digit*pow
end
end
base_n_to_base_10([1, 2, 3], 10)
#=> 123
base_n_to_base_10([1, 0, 0, 0, 0, 0, 1, 1], 2)
#=> 131
base_n_to_base_10([4, 13, 2], 16)
#=> 1234
base_n_to_base_10([93, 27], 99)
#=> 9234
Как и ожидалось, если
radix = 87
n10 = 6257
base87 = base10_to_base_n(n10, radix)
#=> [71, 80]
, то:
base_n_to_base_10(base10_to_base_n(n10, radix), radix)
#=> 6257
base10_to_base_n(base_n_to_base_10(base87, radix), radix)
#=> [71, 80]