Класс Math и пакет java.math
Класс Math содержит методы, связанные с геометрией и тригонометрией и прочей математики. Методы реализованы как static, поэтому можно сразу вызывать через Math.methodName() без создания экземпляра класса.
В классе определены две константы типа double: E и PI.
Популярные методы для тригонометрических функций принимают параметр типа double, выражающий угол в радианах.
- sin(double d)
- cos(double d)
- tan(double d)
- asin(double d)
- acos(double d)
- atan(double d)
- atan2(double y, double x)
Существуют также гиперболические функции: sinh(), cosh(), tanh().
Из них хорошо знакомы возведение в степень — pow(2.0, 3.0) вернёт 8.0.
Также популярен метод для извлечения квадратного корня — sqrt(4.0). Если аргумент меньше нуля, то возвращается NaN. Похожий метод cbrt() извлекает кубический корень. Если аргумент отрицательный, то и возвращаемое значение будет отрицательным: -27.0-> -3.0.
- abs() — возвращает абсолютное значение аргумента
- ceil() — возвращает наименьшее целое число, которое больше аргумента
- floor() — возвращает наибольшее целое число, которое меньше или равно аргументу
- max() — возвращает большее из двух чисел
- min() — возвращает меньшее из двух чисел
- nextAfter() — возвращает следующее значение после аргумента в заданном направлении
- nextUp() — возвращает следующее значение в положительном направлении
- rint() — возвращает ближайшее целое к аргументу
- round() — возвращает аргумент, округлённый вверх до ближайшего числа
- ulp() — возвращает дистанцию между значением и ближайшим большим значением
- copySign() — возвращает аргумент с тем же знаком, что у второго аргумента
- getExponent() — возвращает экспоненту
- IEEEremainder() — возвращает остаток от деления
- hypot() — возвращает длину гипотенузы
- random() — возвращает случайное число между 0 и 1 (единица в диапазон не входит)
- signum() — возвращает знак значения
- toDegrees() — преобразует радианы в градусы
- toRadians() — преобразует градусы в радианы
Вычислим наибольшее и наименьшее числа из двух заданных значений.
Большие числа
Если вам не хватает точности основных типов для представления целых и вещественных чисел, то можно использовать классы BigInteger и BigDecimal из пакета java.math, которые предназначены для выполнения действий с числами, состоящими из произвольного количества цифр.
Для преобразования обычного числа в число с произвольной точностью (называемое большим числом) вызывается статический метод valueOf():
При работе с большими числами нельзя использовать привычные математические операции с помощью + или * и т.п. Вместо них следует использовать специальные методы add() (сложение), multiply() (умножение), divide() (деление) и т.д.
В обычной практике эти числа используются редко.
Источник
Дополнительные классы
Математические вычисления и класс Math
Для выполнения различных математических операций в Java в пакете java.lang определен класс Math . Рассмотрим его основные методы:
abs(double value) : возвращает абсолютное значение для аргумента value
acos(double value) : возвращает арккосинус value. Параметр value должен иметь значение от -1 до 1
asin(double value) : возвращает арксинус value. Параметр value должен иметь значение от -1 до 1
atan(double value) : возвращает арктангенс value
cbrt(double value) : возвращает кубический корень числа value
ceil(double value) : возвращает наименьшее целое число с плавающей точкой, которое не меньше value
cos(double d) : возвращает косинус угла d
cosh(double d) : возвращает гиперболический косинус угла d
exp(double d) : возвращает основание натурального логарифма, возведенное в степень d
floor(double d) : возвращает наибольшее целое число, которое не больше d
floorDiv(int a, int b) : возвращает целочисленный результат деления a на b
log(double a) : возвращает натуральный логарифм числа a
log1p(double d) : возвращает натуральный логарифм числа (d + 1)
log10(double d) : возвращает десятичный логарифм числа d
max(double a, double b) : возвращает максимальное число из a и b
min(double a, double b) : возвращает минимальное число из a и b
pow(double a, double b) : возвращает число a, возведенное в степень b
random() : возвращает случайное число от 0.0 до 1.0
rint(double value) : возвращает число double, которое представляет ближайшее к числу value целое число
round(double d) : возвращает число d, округленное до ближайшего целого числа
scalb(double value, int factor) : возвращает произведение числа value на 2 в степени factor
signum(double value) : возвращает число 1, если число value положительное, и -1, если значение value отрицательное. Если value равно 0, то возвращает 0
sin(double value) : возвращает синус угла value
sinh(double value) : возвращает гиперболический синус угла value
sqrt(double value) : возвращает квадратный корень числа value
tan(double value) : возвращает тангенс угла value
tanh(double value) : возвращает гиперболический тангенс угла value
toDegrees(double value) переводит радианы в градусы и toRadians(double value) — градусы в радианы
Источник
Математический пакет для Android своими руками
Мне понравилась дискуссия, развернувшаяся по поводу этой статьи. Однако мне более интересен немного иной аспект дискутируемой проблемы, а именно: нужна ли система компьютерной алгебры на смартфоне или планшете, или это такой странный таракан в голове околоайтишного инженера?
Постановка проблемы
Как известно, тяжела и неказиста жизнь простого программиста. Около года назад, когда я осознал вычислительные возможности своего китайфона с четырьмя ядрами на платформе Android, захотелось тряхнуть своей научной стариной и что-нибудь посчитать на телефоне. Play-маркет может все, подумалось тогда.
Каких-то особых ограничений не было, за свою научную карьеру я успел попользовать и Mathcad с MATLAB, и Математику, и FEM-системы (Ansys). Поэтому для начала стал смотреть все подряд.
Сложилась такая картина (я не буду приводить ссылки, желающие легко могут найти это на Play-маркете):
- Matlab Mobile, как расширение лицензионной копии десктопного варианта. У меня таковой дома не оказалось, поэтому этот вариант, к сожалению, отпал;
- Сервис Wolfram Alpha и туча обучалок от Wolfram Group — не совсем то, что у меня ассоциируется со словами «посчитать самостоятельно»;
- Клоны «Матлаба» и «Октавы» под Android — уже теплей, но писать код на экране в 5 дюймов не очень-то удобно;
- Огромное количество научных калькуляторов разной степени навороченности. Их всех объединяет одно — ввод и представление результатов организованы как в классическом (хардверном) графическом калькуляторе. Основной минус такой идеи — это отсутствие «документа», который можно сохранять, изменять и пересчитывать вновь и вновь;
- Ничего, что походило бы на Маткад, тогда найти не удалось.
Почему я здесь и в начале поста упомянул про Mathcad? На мой взгляд, эта идея хорошо подходит под задачи мобильной математики:
- На небольшом экране устройства с пальце-ориентированным интерфейсом все-же удобней работать с формулой, если она записана в естественном математическом виде, а не в виде кода на скриптовом языке;
- Мобильное устройство хорошо подходит для того, чтобы что-то быстро попробовать. Поэтому от мобильной математической системы требуется удобный интерфейс, но не требуется серьезных вычислительных возможностей;
- В идеале, в такой системе нужна функция «Я пиарюсь». То есть не только быстро записать сложную формулу и построить пару графиков, но и удобно опубликовать это во всех своих социальных сетях. Формулы в естественной математической нотации здесь тоже более удобны, чем скрипт.
То есть я бы с удовольствием установил бы Mathcad mobile на свой смартфон. Но вот его-то (в смысле «Маткада», а не смартфона) на Play-маркете и не оказалось. Отсюда и родилась идея разработать нечто подобное самостоятельно.
Формулировка задачи
Итак, я решил написать с нуля Андроид-приложение, предназначенное для создания и работы с математическими вычисляемыми документами.
Требования к приложению я сформулировал так:
- Максимально широкий охват поддерживаемых устройств. Отсюда минимальный API level 8;
- Поддержка экранов различных разрешений и ландшафтной/портретной ориентации;
- Формат хранения документов — свой на основе XML;
- Подробная документация. Чтобы не плодить сущностей, для документирования используется тот же самый формат, в котором хранятся сами документы;
- Для создания печатной документации предусмотреть экспорт в LaTeX, так как он удобен для записи формул и дает возможность сгенерировать PDF;
- Математика безгранична. Все не реализовать. Поэтому начальный функционал включает в себя функции многих переменных, графики (2D и 3D), численное интегрирование и дифференцирование, логический оператор. Далее в зависимости от хотелок пользователей;
- Возможность вставки текста и изображений, но функционал редактирования текста для начала минимальный;
- Удобность использования и качество имеют приоритет над функционалом;
- Языки только те, что знаю сам и смогу развивать и поддерживать без обращения к переводчику.
И, наверное, самое главное. Это — хобби. Поэтому важно оставаться реалистом и не замахиваться на то, что невозможно реализовать одному человеку за разумное время в режиме 5-6 дней в неделю по 2 часа.
Так как проект получил статус «любимое хобби на ближайший год», то отсюда два важных следствия:
- Я решил не ограничивать себя в разумных тратах на технику/продвижение/услуги, если таковые потребуются;
- Такие цели, как «Заработать любой ценой» и «Оказаться в топе» не ставятся, поэтому я решил не добавлять рекламу в приложения и отказаться от продвижения через мотивированные загрузки.
В то же время, я противник полной халявы. Поэтому выбрал следующую модель монетизации:
- Само приложение является платным и распространяется только через Play-маркет;
- Имеется бесплатная версия с идентичным внешним видом и интерфейсом, но с урезанной математикой. Причем этот функционал не деактиварован, а отсутствует на уровне кода. То есть бесплатную версию физически нельзя переключить в полный режим и она распространяется везде, где только можно.
Такая модель легко реализуется с использованием системы контроля версий (в моем случае SVN), где основная ветка предназначена для экспериментов и разработки, а две дочерние — для релизов платной и бесплатной версий соответственно.
На этом можно подвести черту под вводными данными и приступить к обсуждению реализации.
Метод решения
На мой взгляд, самый главный вопрос такой — как организовать на смартфоне ввод и редактирование формул, которые можно вычислять (для начала только численно), но при этом они представлены в естественном математическом виде? Как скомпоновать из этих формул, графиков, текста и загружаемых из файла картинок единый документ, способный самовычисляться?
Многие из вас наверняка использовали вордовский редактор формул. На большом экране, да с клавиатурой и мышкой под рукой все очень просто. На экране видны различные математические палитры (или легко доступны из меню), мышкой позиционируется курсор, а далее либо с клавиатуры, либо мышкой из палитры вводится нужный символ. Часть формулы можно легко выделить мышкой, скопировать, заменить или перетащить в другое место. Сами формулы как плавающие объекты можно перетащить мышкой в любую часть документа. Знакомо, да?
А теперь то же самое на сенсорном экране, без мышки, без хардверной клавиатуры, где виртуальная клавиатура перекрывает треть (в ландшафтной ориентации половину) экрана?
Начну с компоновки объектов в документе. Вариантов, на самом деле, не очень много:
- Каждый объект имеет свои координаты и объекты могут располагаться относительно друг друга произвольно, как в векторном графическом редакторе. Именно этот вариант реализован в самом Маткаде. Под Андроидом можно использовать для этого устаревший AbsoluteLayout, но при этом необходимо реализовать выравнивание/распределение объектов и групп объектов. То есть в этом варианте нужен дополнительный пользовательский интерфейс, не относящийся к основной задаче. Для настольного компьютера это не критично, однако юзабилити мобильного приложения, на мой взгляд, от этого будет хуже;
- Расположение в ячейках таблицы, как в MS Excel. Этот вариант я отмел сразу, так как математический документ — это все что угодно, но только не таблица;
- Простой список, где каждый объект в своей строке. Именно так устроены большинство научных калькуляторов. Именно это я и реализовал в первой версии приложения. Дешево и сердито. На что получил вполне резонные замечания пользователей, что такой метод очень неудобен, так как есть объективная потребность группировать некоторые формулы по строкам;
- В результате получилась упрощенная версия RelativeLayout, этакий двумерный список, где по умолчанию объекты добавляются вертикально (снизу выделенного объекта), но с помощью одного единственного окна можно добавить объект как справа, так и слева от выделенного:
Пока я отказался от режима захвата и перетаскивания объектов при движении пальца по экрану, так как такой интерфейс в случае двумерного списка требует некоторой проработки. Вместо этого реализована возможность группового выделения объектов и групповые операции через контекстное меню: удаление, копирование в буфер и замена выделенного объекта содержимым из буфера.
Следующий вопрос связан со вводом информации. Многие калькуляторы имеют для этого свою виртуальную математическую клавиатуру. Мне же этот подход не кажется оптимальным. К примеру, я сам использую планшет с внешней USB клавиатурой, и в этом случае он имеет ландшафтную ориентацию. Выкатывать в такой ситуации виртуальную клавиатуру, которая занимает половину экрана, не совсем логично. Поэтому я изначально нацелился на то, что приложение будет работать со стандартной системной клавиатурой и не требовать специальных клавиатурных расширений. То есть абсолютно все математические символы можно ввести в виде кода с клавиатуры, и эта идея опять же позаимствована из Маткада. Для ввода греческих символов я просто добавил греческий язык к клавиатурным раскладкам.
Однако вынуждать пользователя запоминать все коды — не есть хорошая идея. Поэтому внизу экрана, вне зависимости от ориентации, расположена вторая панель инструментов, по оформлению и размерам идентичная верхней основной. Все математические символы, коих сейчас около 50-ти, расположены в одну линию на этой панели, а сама она прокручивается вправо и влево. При коротком нажатии символ вводится. При долгом нажатии на символ всплывает подсказка, что это и какой код ему соответствует:
В подтверждение этой идеи хочу процитировать отзыв одного из пользователей: «Beeing able to use shortcuts instead of symbolic buttons (but not beeing forced to do so) makes the app perfect».
А куда вводятся коды или символы? Здесь опять все похоже на Маткад. При добавлении объекта появляются пустые поля ввода. В них можно вводить текст, числа или символы. При вводе, например, символа деления вместо поля ввода появляется дробь с двумя полями, в одно из которых перекочует текст, введенный ранее в удаленном поле. Это основной режим ввода, который хорош, когда точно знаешь последовательность набора нужной формулы:
А если не знаешь или нужно что-то изменить в формуле? Контекстное меню в помощь. Оно активируется при долгом нажатии на часть формулы и предоставляет доступ к буферу обмена. Кроме этого, там есть кнопка расширения области выделения. С нижней панели инструментов можно ввести символ, который будет применен к выделенному блоку:
Получилась своего рода кооперация. Пользователь, вводя формулу таким методом, сам же и выполняет основную работу по ее синтаксическому разбору. А приложение в благодарность за это формулу просчитает.
Таким образом, каждая формула имеет два аспекта:
- Во-первых, это иерархия вложенных лайаутов, которые содержат как поля ввода, так и математические обозначения. Визуально это обычная формула.
Подводные камни
И вот здесь меня поджидала серьезная засада. Де-факто в Андроиде есть ограничение на количество вложенных лайаутов, связанное с размером стека вызова процедур. Компилятор в этом случае ничего не скажет, но во время работы (в методе android.view.View.draw одного из вложенных лайаутов) приложение валится с исключением типа StackOverflowErrors. Подробнее об этом здесь.
Отловить это исключение реально, так как у меня имеется собственная реализация метода onDraw() в самом начале этой цепочки вызовов, но при этом, начиная с определенной сложности формулы, она просто перестанет прорисовываться. Пришлось вручную контролировать глубину вложений элементов формулы, и, начиная с некоторой критической глубины (подобранной экспериментально), выдавать несимпатичное, но все-же необходимое сообщение «К сожалению, достигнут предел глубины формулы для данной версии Андроида».
Экспериментально я подобрал следующие значения предельной глубины, считая от корневого RelativeLayout фрагмента:
- если API level 17 (4.3.x и выше), то 15 уровней.
Вторая проблема — отсутствие стандартной компоненты, которая бы сочетала в себе горизонтально-вертикальный скроллинг и масштабирование. Эти действия вроде как поддерживаются WebView, но вот сама WebView мне никак не подходит. Решение топорное, но работает — я взял исходники стандартных ScrollView и HorizontalScrollView, объединил их в одну компоненту и прикрутил детектирование и обработку изменения масштаба. Что я при этом так и не смог довести до ума — это корректное позиционирование в документе после изменения масштаба.
Документация и локализация
Читая отзывы пользователей на Play-маркете про различные научные калькуляторы, я обнаружил, что одним из слабых мест большинства калькуляторов является отсутствие документации. Иногда полное. Поэтому я решил уделить документации достаточно много внимания. И добавил ее как в само приложение (для этой цели удобным оказалось боковое меню NavigationDraver), так и выложил в сети в виде PDF и добавил в приложение ссылки для прямой загрузки.
В приложении разделы документации хранятся в XML и открываются как отдельные фреймы. Имеется функция конвертации документа в LaTeX. Утилита pdfletx на рабочем месте довершает дело. Результат не стыдно выставить на всеобщее обозрение.
Теперь пару слов про локализацию. Разработка по старой привычке ведется на английском. Когда программа откомпилировалась и запустилась (то есть готова к продаже), интерфейс и документация вновь добавленной фишки переводятся на два других языка, один из которых русский.
И вот тут я был приятно удивлен статистикой загрузок в консоли разработчика. Математика в Рунете в почете! К слову сказать, русскую версию я выпустил не сразу, а когда количество загрузок приблизилось к тысяче. Но это практически не увеличило и без того высокий процент загрузок из России и стран ближнего зарубежья. На текущий момент распределение загрузок для бесплатной версии по языкам и странам выглядит так:
То есть Россия, Украина и Казахстан вместе обеспечивают более 40% загрузок. Платная версия дает другую картину: загрузки из России доминируют лишь с незначительным отрывом.
Заключение
Ну что же, написано уже много, пора закругляться. С вычислительной точки зрения очень многие нужные вещи еще не реализованы: нет комплексных чисел, нет поддержки массивов, нет даже примитивной матричной арифметики, нет решения уравнений. Но тут возникает резонный вопрос — а надо ли это на телефоне? Интересно услышать мнение уважаемой аудитории.
Что касается ближайших задач, то пока основные пожелания пользователей касаются наращивания экспортных возможностей. К примеру, один из последних комментариев: «Интересует такой вопрос, есть хоть какая нибудь возможность связать документ с маткадом? Что бы была возможность доработать документ на ПК». По поводу Маткада лично я сомневаюсь, так как формат проприетарный, но такие вещи, как экспорт в HTML (буквально сегодня обнаружил фреймворк MathJax), в PDF, или какой-нибудь открытый офисный формат можно реализовать.
На этом хочу хочу поблагодарить за внимание всех, кто дочитал до конца, и с чувством выполненного долга откланяться. Буду рад вопросам, если таковые появятся.
Источник