Переменные, числа и арифметика

Переменная — это имя, привязанное к значению. В Ruby её не нужно объявлять заранее и указывать тип: присвоили значение — переменная появилась.
Суть: переменные в Ruby — это ссылки на объекты, имена пишутся через snake_case, а числа делятся на целые (Integer) и дробные (Float), причём деление целых даёт целое.

Динамическая типизация Ruby означает, что одна и та же переменная может в разные моменты ссылаться на число, строку или массив. Тип принадлежит значению, а не имени. Это даёт гибкость, но требует внимательности: Ruby не предупредит на этапе «компиляции», что вы складываете строку с числом.

age = 25
price = 19.99
total = age * 2
puts total            # => 50
puts price.class      # => Float
puts age.class        # => Integer

Разбор: целые против дробных

Главная ловушка арифметики — деление целых чисел. 7 / 2 в Ruby равно 3, а не 3.5, потому что оба операнда целые и результат тоже целый. Чтобы получить дробь, хотя бы один операнд должен быть Float.

puts 7 / 2            # => 3   (целочисленное деление)
puts 7.0 / 2          # => 3.5 (есть Float — результат Float)
puts 7 % 2            # => 1   (остаток от деления)
puts 2 ** 10          # => 1024 (возведение в степень)
puts 7.fdiv(2)        # => 3.5 (явное дробное деление)

Та же логика на Python работает идентично по сути (целые против дробных), хотя в Python 3 оператор / всегда даёт дробь, а целочисленное — это //:

# Та же логика на Python ▶
print(7 // 2)    # 3  целочисленное деление
print(7 / 2)     # 3.5 обычное деление
print(7 % 2)     # 1  остаток
print(2 ** 10)   # 1024 степень

Как работает под капотом

Когда вы пишете x = "hello", переменная x не «содержит» строку — она хранит ссылку на объект-строку в памяти. Если вы напишете y = x, обе переменные будут указывать на один и тот же объект. Это важно понимать сразу, потому что изменение объекта через одну ссылку увидят все остальные.

x = "hello"          y = x

  x ---> [ "hello" ]      x ---> [ "hello" ]
                              y -----^
        (один объект, две ссылки)

Числа же в Ruby ведут себя как неизменяемые (immutable) значения: операция x + 1 не меняет старое число, а создаёт новое. Поэтому с числами «общая ссылка» проблем не создаёт.

Частые ошибки

  • Целочисленное деление там, где ждали дробь. average = sum / count при целых даст округлённый вниз результат. Используйте fdiv или приведите к Float.
  • camelCase в именах. В Ruby принято snake_case: user_name, а не userName. Имя с заглавной — это уже константа.
  • Сложение строки и числа. "возраст: " + 25 упадёт с ошибкой. Нужна интерполяция или .to_s.

Best practices

  • Давайте переменным говорящие имена: total_price лучше, чем tp или x.
  • Большие числа разделяйте подчёркиванием для читаемости: 1_000_000 — это валидный синтаксис и равно миллиону.
  • Если нужна точность в деньгах, не используйте Float (он округляет неточно) — берите BigDecimal или храните копейки в целых.

Глубже: типы чисел и точность

Стоит чуть подробнее разобраться с числовыми типами, потому что на них основано множество тонких ошибок. Целые числа (Integer) в Ruby не имеют верхнего предела: язык автоматически переключается на «длинную арифметику», когда число перестаёт помещаться в машинное слово. Поэтому 100 ** 100 честно посчитается без переполнения — приятное отличие от языков с фиксированным размером целых. Дробные числа (Float) хранятся в формате двойной точности IEEE 754, и здесь кроется классическая ловушка: 0.1 + 0.2 не равно ровно 0.3, потому что эти дроби не представимы точно в двоичной системе. Для обычных вычислений это незаметно, но в деньгах или сравнениях на равенство — катастрофа. Решений два: либо работать с целыми (хранить копейки, а не рубли), либо использовать класс BigDecimal, который считает в десятичной системе без потери точности. Запомните это правило сразу: Float — для приблизительных величин, BigDecimal или целые — для денег.

Итог. Переменные — это именованные ссылки на объекты, тип динамический и принадлежит значению. Помните о ловушке целочисленного деления и пишите имена через snake_case.

Проверьте себя
1. Чему равно выражение 7 / 2 в Ruby?
A3.5
B3
C4
DОшибка
2. Как принято именовать переменные в Ruby?
AcamelCase, например userName
Bsnake_case, например user_name
CС заглавной буквы, например UserName
DВЕРХНИМ_РЕГИСТРОМ