Хэл Фултон - Программирование на языке Ruby
- Название:Программирование на языке Ruby
- Автор:
- Жанр:
- Издательство:ДМК Пресс
- Год:2007
- Город:Москва
- ISBN:5-94074-357-9
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Хэл Фултон - Программирование на языке Ruby краткое содержание
Ruby — относительно новый объектно-ориентированный язык, разработанный Юкихиро Мацумото в 1995 году и позаимствовавший некоторые особенности у языков LISP, Smalltalk, Perl, CLU и других. Язык активно развивается и применяется в самых разных областях: от системного администрирования до разработки сложных динамических сайтов.
Книга является полноценным руководством по Ruby — ее можно использовать и как учебник, и как справочник, и как сборник ответов на вопросы типа «как сделать то или иное в Ruby». В ней приведено свыше 400 примеров, разбитых по различным аспектам программирования, и к которым автор дает обстоятельные комментарии.
Издание предназначено для программистов самого широкого круга и самой разной квалификации, желающих научиться качественно и профессионально работать на Ruby.
Программирование на языке Ruby - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
x = BigDecimal ("1.234",10)
y = BigDecimal("1.234",15)
x.precs # [8, 16]
y.precs # [8, 20]
В каждый момент число использованных байтов может оказаться меньше максимального. Максимум может также оказаться больше запрошенного вами (поскольку BigDecimal
пытается оптимизировать использование внутренней памяти). У обычных операций (сложение, вычитание, умножение и деление) есть варианты принимающие в качестве дополнительного параметра число значащих цифр. Если результат содержит больше значащих цифр, чем указано, производится округление до заданного числа знаков.
a = BigDecimal("1.23456")
b = BigDecimal("2.45678")
# В комментариях "BigDecimal:objectid" опущено.
c = a+b # <'0.369134Е1\12(20)>
c2 = a.add(b,4) # <'0.3691Е1',8(20)>
d = a-b # <'-0.122222E1',12(20)>
d2 = a.sub(b,4) # <'-0.1222E1',8(20)>
e = a*b # <'0.30330423168E1\16(36)>
e2 = a.mult(b,4) # <'0.3033E1',8(36)>
f = a/b # <'0.502511417383729922907221E0',24(32)>
f2 = a.div(b,4) # <'0.5025E0',4(16)>
В классе BigDecimal
определено и много других функций, например floor
, abs
и т.д. Как и следовало ожидать, имеются операторы %
и **
, а также операторы сравнения, к примеру <
. Оператор ==
не умеет округлять свои операнды — эта обязанность возлагается на программиста.
В модуле BigMath
определены константы E
и PI
с произвольной точностью. (На самом деле это методы, а не константы.) Там же определены функции sin
, cos
, exp
и пр.; все они принимают число значащих цифр в качестве параметра. Следующие подбиблиотеки являются дополнениями к BigDecimal
.
bigdecimal/math
Модуль BigMath
bigdecimal/jacobian
Методы для вычисления матрицы Якоби
bigdecimal/ludcmp
Модуль LUSolve
, разложение матрицы в произведение верхнетреугольной и нижнетреугольной
bigdecimal/newton
Методы nlsolve
и norm
В настоящей главе эти подбиблиотеки не описываются. Для получения дополнительной информации обратитесь к сайту ruby-doc.org или любому подробному справочному руководству.
5.9. Работа с рациональными числами
Класс Rational
позволяет (во многих случаях) производить операции с дробями с «бесконечной» точностью, но лишь если это настоящие рациональные числа (то есть частное от деления двух целых чисел). К иррациональным числам, например π или e, он неприменим.
Для создания рационального числа мы вызываем специальный метод Rational
(еще один из немногих методов, имя которого начинается с прописной буквы; обычно такие методы служат для преобразования данных или инициализации).
r = Rational(1,2) # 1/2 или 0.5
s = Rational(1,3) # 1/3 или 0.3333...
t = Rational(1,7) # 1/7 или 0.14...
u = Rational(6,2) # "то же самое, что" 3.0
z = Rational(1,0) # Ошибка!
Результатом операции над двумя рациональными числами, как правило, снова является рациональное число.
r+t # Rational(9, 14)
r-t # Rational(5, 14)
r*s # Rational(1, 6)
r/s # Rational(3, 2)
Вернемся к примеру, на котором мы демонстрировали неточность операций над числами с плавающей точкой (см. раздел 5.4). Ниже мы выполняем те же действия над рациональными, а не вещественными числами и получаем «математически ожидаемый» результат:
x = Rational(1000001,1)/Rational(3,1000)
y = Rational(3,1000)*x
if y == 1000001.0
puts "да" # Теперь получаем "да"!
else
puts "нет"
end
Конечно, не любая операция дает рациональное же число в качестве результата:
x = Rational (9,16) # Rational(9, 16)
Math.sqrt(x) # 0.75
x**0.5 # 0.75
x**Rational(1,2) # 0.75
Однако библиотека mathn
в какой-то мере изменяет это поведение (см. раздел 5.12).
5.10. Перемножение матриц
Стандартная библиотека matrix
предназначена для выполнения операций над числовыми матрицами. В ней определено два класса: Matrix
и Vector
.
Следует также знать о прекрасной библиотеке NArray
, которую написал Масахиро Танака (Masahiro Tanaka) — ее можно найти на сайте www.rubyforge.org. Хотя эта библиотека не относится к числу стандартных, она широко известна и очень полезна. Если вы предъявляете повышенные требования к быстродействию, нуждаетесь в особом представлении данных или желаете выполнять быстрое преобразование Фурье, обязательно ознакомьтесь с этим пакетом. Впрочем, для типичных применений стандартной библиотеки matrix
должно хватить, поэтому именно ее мы и рассмотрим.
Чтобы создать матрицу, мы, конечно же, обращаемся к методу класса. Сделать это можно несколькими способами. Самый простой — вызвать метод Matrix.[]
и перечислить строки в виде массивов. Ниже мы записали вызов на нескольких строчках, но, разумеется, это необязательно:
m = Matrix[[1,2,3],
[4,5,6],
[7,8,9]]
Вместо этого можно вызвать метод rows, передав ему массив массивов (в таком случае «дополнительные» скобки необходимы). Необязательный параметр сору, по умолчанию равный true, указывает, надо ли скопировать переданные массивы или просто сохранить на них ссылки. Оставляйте значение true, если нужно защитить исходные массивы от изменения, и задавайте false, если это несущественно.
Row1 = [2,3]
row2 = [4,5]
m1 = Matrix.rows([row1,row2]) # copy=true
m2 = Matrix.rows([row1,row2],false) # He копировать.
row1[1] = 99 # Теперь изменим row1.
p m1 # Matrix[[2, 3], [4, 5]]
p m2 # Matrix[[2, 99], [4, 5]]
Можно задать матрицу и путем перечисления столбцов, если воспользоваться методом columns
. Ему параметр сору
не передается, потому что столбцы в любом случае расщепляются, так как во внутреннем представлении матрица хранится построчно:
m1 = Matrix.rows([[1,2],[3,4]])
m2 = Matrix.columns([[1,3],[2,4]]) # m1 == m2
Предполагается, что все матрицы прямоугольные, но это не проверяется. Если вы создадите матрицу, в которой отдельные строки или столбцы длиннее либо короче остальных, то можете получить неверные или неожиданные результаты.
Некоторые специальные матрицы, особенно квадратные, конструируются проще. Так, тождественную матрицу конструирует метод identity
(или его синонимы I
и unit
):
im1 = Matrix.identity(3) # Matrix[[1,0,0],[0,1,0],[0,0,1]]
im2 = Matrix.I(3) # То же самое.
im3 = Matrix.unit(3) # То же самое.
Более общий метод scalar
строит диагональную матрицу, в которой все элементы на диагонали одинаковы, но не обязательно равны 1:
sm = Matrix.scalar(3,8) # Matrix[[8,0,0],[0,8,0],[0,0,8]]
Еще более общим является метод diagonal
, который формирует диагональную матрицу с произвольными элементами (ясно, что параметр, задающий размерность, в этом случае не нужен).
dm = Matrix.diagonal(2,3,7) # Matrix[[2,0,0],[0,3,0],[0,0,7]]
Метод zero
создает нулевую матрицу заданной размерности (все элементы равны 0):
zm = Matrix.zero(3) # Matrix[[0,0,0],[0,0,0],[0,0,0]]
Понятно, что методы identity
, scalar
, diagonal
и zero
создают квадратные матрицы.
Интервал:
Закладка: