Как правильно работать с ведущими нулями в Ruby?

0112.to_s
 => "74"
0112.to_i
 => 74

Почему он конвертирует 0112 в 74?

Как преобразовать 0112 в строку "0112"?


Я хочу определить метод, который принимает целое число в качестве аргумента и возвращает его с цифрами в порядке убывания.

Но это, похоже, не работает для меня, когда у меня есть ведущие нули:

def descending_order(n)
  n.to_s.reverse.to_i
end
10
Joel 16 Фев 2015 в 19:06

2 ответа

Лучший ответ

Числовой литерал, начинающийся с 0, является восьмеричным представлением, за исключением литералов, начинающихся с 0x, которые представляют шестнадцатеричные числа, или 0b, которые представляют двоичные числа.

1 * 8**2 + 1 * 8**1 + 2 * 8**0 == 74

Чтобы преобразовать его в 0112, используйте String#% или Kernel#sprintf с соответствующей строкой формата:

'0%o' % 0112  # 0: leading zero, %o: represent as an octal
# => "0112"
13
the Tin Man 16 Фев 2015 в 17:36

Вы не можете, потому что класс Ruby Integer не хранит начальные нули.

Начальный 0 в числовом литерале интерпретируется как префикс:

  • 0 и 0o: восьмеричное число
  • 0x: шестнадцатеричное число
  • 0b: двоичное число
  • 0d: десятичное число

Это позволяет вам вводить числа в эти базы. Парсер Ruby преобразует литералы в соответствующие экземпляры Integer. Префикс или ведущие нули отбрасываются.

Другой пример - %w для ввода массивов:

ary = %w(foo bar baz)
#=> ["foo", "bar", "baz"]

Невозможно получить это %w от ary. Парсер превращает литерал в экземпляр массива, поэтому сценарий никогда не видит литерал.

0112 (или 0o112) интерпретируется (анализатором) как восьмеричное число 112 и превращается в целое число 74.

Десятичное число 0112 - это просто 112, независимо от того, сколько нулей вы поставите впереди:

0d0112   #=> 112
0d00112  #=> 112
0d000112 #=> 112

Это как дополнительные нули в конце для чисел с плавающей запятой:

1.0   #=> 1.0
1.00  #=> 1.0
1.000 #=> 1.0

Вероятно, вам придется использовать строку, например "0112"

Другой вариант - явно указать (минимальную) ширину, например:

def descending_order(number, width = 0)
  sprintf('%0*d', width, number).reverse.to_i
end

descending_order(123, 4)
#=> 3210

descending_order(123, 10)
#=> 3210000000
6
Stefan 16 Фев 2015 в 18:15