При чтении данных из файла или другого внешнего ресурса данные всегда приходят в Ruby как объекты String (Строка).
Если мы хотим использовать их как числа, сначала их нужно сконвертировать в числа.
Но в какие и как?
Объект String в Ruby имеет несколько методов конверации в число.
-
to_i
сконвертирует String в Integer. -
to_f
сконвертирует String во Float (с плавающей точкой) -
to_r
сконвертирует String в Rational number (рациональное число). -
to_c
сконвертирует String в Complex number (комплексное число).
Конкатенация
Если для двух числовых значений, которые на самом деле объекты String
(из-за обрамляющих кавычек), использовать оператор +
,
то он будет работать как конкатенация.
a = "2"
b = "3"
puts a+b # 23
no implicit conversion of Fixnum into String (TypeError)
Если одно из значений это объект String
, а другое - число (без кавычек), и мы попробуем сложить их друг с другом, как в примере:
puts "2"+3
мы получим исключение: no implicit conversion of Fixnum into String (TypeError)
String, которые выглядят как integer
String
, содержащие целое число (integer) могут быть сконвертированы в Integer, Float, Rational number, или Complex number:
puts a.to_i # 2
puts a.to_f # 2.0
puts a.to_r # 2/1
puts a.to_c # 2+0i
Как задать основание: конвертация двоичных, восьмеричных, шестнадцатеричных значений в десятичные
По умолчанию to_i
предполагает, что наш объект String представлен в десятичной системе (основание 10), но что если вы хотите это изменить?
Что если вы хотите рассматривать String как двоичное число, восьмеричное или шестнадцатеричное? Тогда нужно просто передать аргумент base=
с подходящим числом в метод to_i
:
puts "11".to_i # 11
puts "11".to_i(base=2) # 3
puts "11".to_i(base=16) # 17
Конечно шестнадцатеричные числа могут также содержать символы a-f. Функция to_i
умеет с ними обращаться.
puts "aB".to_i(base=16) # 171
Возникает вопрос, что случится, если мы используем to_i
без указания основания для строки с шестнадцатеричным числом,
или с основанием, которое не предусматривает таких символов? Тогда просто вернется 0 (без какой-либо ошибки).
puts "aB".to_i # 0
puts "9".to_i(base=8) # 0
Это подводит нас к вопросу: Что случится, если не все символы могут быть сконвертированы в число?
Ответ прост.
to_i
сконвертирует все 'digits' от начала до того места, где уже не будет понятно, что делать.
Оставшаяся часть строки будет отброшена. Даже если там есть еще понимаемые значения.
puts "2x3".to_i # 2
puts "2 3".to_i # 2
Конвертация в число с плавающей точкой или рациональное число
Мы можем использовать остальные методы для конвертации во Floating point (число с плавающей точкой), Rational number (рациональное число), и даже в Complex number (комплексное число):
Некоторые из них понимают точку в десятичной дроби в String
c = "14.6"
puts c.to_i # 14
puts c.to_f # 14.6
puts c.to_r # 73/5
puts c.to_c # 14.6+0i
Некоторые даже понимают символ e
, обозначающий экспоненту в String:
e = "2.3e4x5"
puts e # 2.3e4x5
puts e.to_i # 2
puts e.to_f # 23000.0
puts e.to_r # 23000/1
puts e.to_c # 23000.0+0i
Полный пример
examples/ruby/string_to_number.rb
a = "2"
b = "3"
puts a+b # 23
puts '-------'
# puts "2"+3 # no implicit conversion of Fixnum into String (TypeError)
puts a.to_i # 2
puts a.to_f # 2.0
puts a.to_r # 2/1
puts a.to_c # 2+0i
puts '-------'
puts "11".to_i # 11
puts "11".to_i(base=2) # 3
puts "11".to_i(base=8) # 9
puts "11".to_i(base=16) # 17
puts '-------'
puts "aB".to_i(base=16) # 171
puts "aB".to_i # 0
puts "9".to_i(base=8) # 0
puts '-------'
puts "2x3".to_i # 2
puts "2 3".to_i # 2
puts '-------'
c = "14.6"
puts c.to_i # 14
puts c.to_f # 14.6
puts c.to_r # 73/5
puts c.to_c # 14.6+0i
puts '-------'
e = "2.3e4x5"
puts e # 2.3e4x5
puts e.to_i # 2
puts e.to_f # 23000.0
puts e.to_r # 23000/1
puts e.to_c # 23000.0+0i
puts '-------'