Книга: Программирование на языке Ruby
5.8. Использование класса BigDecimal
5.8. Использование класса BigDecimal
Стандартная библиотека bigdecimal
позволяет работать с дробями, имеющими много значащих цифр. Число хранится как массив цифр, а не преобразуется в двоичное представление. Тем самым достижима произвольная точность, естественно, ценой замедления работы.
Чтобы оценить преимущества, рассмотрим следующий простой фрагмент кода, в котором используются числа с плавающей точкой:
if (3.2 - 2.0) == 1.2
puts "равны"
else
puts "не равны" # Печатается "не равны"!
end
В подобной ситуации на помощь приходит класс BigDecimal
. Однако в случае бесконечных периодических дробей проблема остается. Другой подход обсуждается в разделе 5.9 «Работа с рациональными числами».
Объект BigDecimal
инициализируется строкой. (Объекта типа Float
было бы недостаточно, поскольку погрешность вкралась бы еще до начала конструирования BigDecimal
.) Метод BigDecimal
эквивалентен BigDecimal.new
; это еще один особый случай, когда имя метода начинается с прописной буквы. Поддерживаются обычные математические операции, например +
и *
. Отметим, что метод to_s
может принимать в качестве параметра форматную строку. Дополнительную информацию вы найдете на сайте ruby-doc.org.
require 'bigdecimal'
x = BigDecimal("3.2")
y = BigDecimal("2.0")
z = BigDecimal("1.2")
if (x - y) == z
puts "равны" # Печатается "равны"!
else
puts "не равны"
end
а = x*y*z
a.to_s # "0.768Е1" (по умолчанию: научная нотация)
a.to_s("F") # "7.68" (обычная запись)
Если необходимо, можно задать число значащих цифр. Метод precs
возвращает эту информацию в виде массива, содержащего два числа: количество использованных байтов и максимальное число значащих цифр.
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Е112(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.30330423168E116(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.1. Представление чисел в языке Ruby
- 5.2. Основные операции над числами
- 5.3. Округление чисел с плавающей точкой
- 5.4. Сравнение чисел с плавающей точкой
- 5.5. Форматирование чисел для вывода
- 5.6. Вставка разделителей при форматировании чисел
- 5.7. Работа с очень большими числами
- 5.8. Использование класса BigDecimal
- 5.9. Работа с рациональными числами
- 5.10. Перемножение матриц
- 5.11. Комплексные числа
- 5.12. Библиотека mathn
- 5.13. Разложение на простые множители, вычисление НОД и НОК
- 5.14. Простые числа
- 5.15. Явные и неявные преобразования чисел
- 5.16. Приведение числовых значений
- 5.17. Поразрядные операции над числами
- 5.18. Преобразование системы счисления
- 5.19. Извлечение кубических корней, корней четвертой степени и т.д.
- 5.20. Определение порядка байтов
- 5.21. Численное вычисление определенного интеграла
- 5.22. Тригонометрия в градусах, радианах и градах
- 5.23. Неэлементарная тригонометрия
- 5.24. Вычисление логарифмов по произвольному основанию
- 5.25. Вычисление среднего, медианы и моды набора данных
- 5.26. Дисперсия и стандартное отклонение
- 5.27. Вычисление коэффициента корреляции
- 5.28. Генерирование случайных чисел
- 5.29. Кэширование функций с помощью метода memoize
- 5.30. Заключение
- Восстановление с использованием инструмента gbak
- 3.4. Отношения между классами
- Типы страниц и их использование
- Использование констант
- Использование переменной окружения ISC_PATH
- Использование сервера Yaffil внутри процесса
- Использование CAST() с типами дата
- Использование типов содержимого и столбцов
- Вызов хранимых процедур InterBase с использованием стандартного синтаксиса ODBC
- Использование кнопки Автосумма
- 24.7. Использование программы-твикера
- Использование отдельных процессоров XSLT