factors = 126.prime_division # [[2,1], [3,2], [7,1]]

                             # To есть 2**1 * 3**2 * 7**1

Имеется также метод класса Integer.from_prime_division, который восстанавливает исходное число из его сомножителей. Это именно метод класса, потому что выступает в роли «конструктора» целого числа.

factors = [[2,1],[3,1],[7,1]]

num = Integer.from_prime_division(factors) # 42

Ниже показано, как разложение на простые множители можно использовать для отыскания наименьшего общего кратного (НОК) двух чисел:

require 'mathn'

class Integer

 def lcm(other)

  pf1 = self.prime_division.flatten

  pf2 = other.prime_division.flatten

  h1 = Hash[*pf1]

  h2 = Hash[*pf2]

  hash = h2.merge(h1) {|key,old,new| [old,new].max }

  Integer.from_prime_division(hash.to_a)

 end

end

p 15.1cm(150) # 150

p 2.1cm(3)    # 6

p 4.1cm(12)   # 12

p 200.1cm(30) # 600

5.14. Простые числа

В библиотеке mathn есть класс для порождения простых чисел. Итератор each возвращает последовательные простые числа в бесконечном цикле. Метод succ порождает следующее простое число. Вот, например, два способа получить первые 100 простых чисел:

require 'mathn'

list = []

gen = Prime.new

gen.each do |prime|

 list << prime

 break if list.size == 100

end

# или:

list = []

gen = Prime.new

100.times { list << gen.succ }

В следующем фрагменте проверяется, является ли данное число простым. Отметим, что если число велико, а машина медленная, то на выполнение может уйти заметное время:

require 'mathn'

class Integer

 def prime?

  max = Math.sqrt(self).ceil

  max -= 1 if max % 2 == 0

  pgen = Prime.new

  pgen.each do |factor|

   return false if self % factor == 0

   return true if factor > max

  end

 end

end

31.prime?         # true

237.prime?        # false

1500450271.prime? # true

5.15. Явные и неявные преобразования чисел

Программисты, только начинающие изучать Ruby, часто удивляются, зачем нужны два метода to_i и to_int (и аналогичные им to_f и to_flt). В общем случае метод с коротким именем применяется для явных преобразований, а метод с длинным именем — для неявных.

Что это означает? Во-первых, в большинстве классов определены явные конверторы, но нет неявных. Насколько мне известно, методы to_int и to_flt не определены ни в одном из системных классов.

Во-вторых, в своих собственных классах вы, скорее всего, будете определять неявные конверторы, но не станете вызывать их вручную (если только не заняты написанием «клиентского» кода или библиотеки, которая пытается не конфликтовать с внешним миром).

Следующий пример, конечно, надуманный. В нем определен класс MyClass, который возвращает константы из методов to_i и to_int. Такое поведение лишено смысла, зато иллюстрирует идею:

class MyClass

 def to_i

  3

 end

 def to_int

  5

 end

end

Желая явно преобразовать объект класса MyClass в целое число, мы вызовем метод to_i:

m = MyClass.new x = m.to_i # 3

Но при передаче объекта MyClass какой-нибудь функции, ожидающей целое число,

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату