Первые программы
Пример 2. Напишите программу, печатающую сумму первых n членов начинающейся с единицы геометрической прогрессии со знаменателем q.
Рассмотрим сначала решение, основанное на использовании известной формулы для суммы геометрической прогрессии
S = (qn – 1)/(q – 1)
.
Запуск этой программы даёт результат 7, а заменив 3 на 64 и запустив программу ещё раз, мы получим знаменитое «шахматное» [2] число 18446744073709551615.
q=2; n=3
puts(q**n-1)/(q-1)
В Ruby (в отличие от многих других языков) легко работать с большими числами.
Программа содержит три инструкции, первые две из которых присваивают переменным q и n значения 2 и 3 соответственно. Отметим, что сами переменные объектами не являются, а лишь указывают (ссылаются) на различные объекты (в данном случае на числа – объекты класса Fixnum). Далее вычисляется выражение (q**n-1)/(q-1), которое неявно преобразуется в строку и печатается методом puts на стандартный вывод. Вот развёрнутая форма второй инструкции программы: STDOUT.puts ((q**n-1)/(q-1)).to_s, где метод to_s, применяемый к числу, возвращает представление этого числа в виде строки.
Кроме чисел и уже встречавшихся нам строк в языке Ruby существует ещё ряд базовых типов (см. стр. 42), для работы с которыми можно использовать много различных операторов (см. стр. 48), включая стандартные арифметические операторы и оператор присваивания. Имена локальных (другие нам встретятся чуть позже) переменных должны начинаться с маленькой латинской буквы и могут содержать также большие буквы, цифры и символ подчёркивания. Имена констант (например, STDOUT) должны начинаться с большой буквы. Более полная информация об использовании имён приведена на стр. 45.
Другое решение этой задачи, использующее цикл while, требует чуть больших комментариев. Переменные s и i используются в этой программе как аккумулятор для накопления суммы прогрессии и счётчик цикла соответственно. Вначале они обнуляются, а на каждой итерации цикла, выполнение которого продолжается, пока величина i остаётся меньше n, значение s увеличивается на очередной член прогрессии, а значение i – на единицу. После завершения цикла остаётся только напечатать результат. Заметим, что выражение i += а эквивалентно i = i + a.
q=2; n=3
i=s=0
while i
s += q**i
i += 1
end
puts s
Обратите внимание, насколько первый вариант программы проще второго. Ещё важнее, что в последнем случае используется низкоуровневый стиль программирования, который чреват ошибками и которого стараются избегать знатоки Ruby. Кроме того, вторая программа чрезвычайно неэффективна по сравнению с первой (попробуйте найти сумму миллиарда членов прогрессии со знаменателем 0.5 с помощью обеих программ).
Даже хорошее знание лучших языков программирования не заменяет знания математики.
1.3 Использование базовых типов. Часто программы получают данные из файлов, запрашивают их с клавиатуры или берут непосредственно из командной строки. Проиллюстрируем последнюю из этих возможностей на примере решения следующей несложной задачи.
Пример 3. Напишите программу, печатающую сумму цифр десятичного представления натурального числа, задаваемого в командной строке.
После запуска программы test.rb командой ruby test.rb 123 Маша в массиве ARGV окажутся все аргументы командной строки, указанные при её запуске, то есть строки 123 и Маша. Выражение ARGV[0] даёт первый элемент массива (строку 123). Для решения задачи этого достаточно, а более подробно с массивами (Arrays) можно познакомиться, заглянув на стр. 43. Таблица A.10 на стр. 47 содержит перечень наиболее часто используемых предопределённых объектов Ruby–программы (ARGV – один из них).
Так как последняя цифра числа n равна остатку от деления на 10 (n%10), а целочисленное деление на 10 (n/10) равносильно удалению последней цифры, то построить цикл while, вычисляющий требуемую сумму, не слишком сложно. Обратите внимание на метод to_i, преобразующий строку в целое число. Его необходимо делать явно в отличие от вызываемого автоматически при работе puts метода to_s, выполняющего обратное преобразование числа в строку. Запустить эту программу, содержащуюся в файле sum1.rb, можно так: ruby suml.rb 12345.
[2]
Согласно легенде, изобретатель шахмат Сета потребовал от индусского царя Шерама, решившего наградить его, выдать за первую клетку доски одно пшеничное зерно, за вторую – два, за третью – четыре и так далее, вплоть до последней, шестьдесят четвёртой.