Числовая/математическая абстракция Java

В настоящее время я нахожусь в процессе написания приложения, в котором есть довольно много математических вычислений. В некоторых ситуациях эти вычисления необходимо выполнять быстро, и мы можем справиться с небольшой потерей точности, чтобы выполнить математику как можно быстрее. С другой стороны, иногда нам требуется, чтобы вычисления были выполнены очень точно (и есть варианты использования промежуточных значений, когда мы могли бы реализовать свой собственный способ выполнения умножения/деления/сложения/вычитания/степени и т. д., который является более точным, чем float * float (или double * double, я знаю, что float — плохой выбор), но быстрее, чем BigDecimal.multiply(BigDecimal)... или даже что-то вроде apfloat, а не BigDecimal).

Существуют ли какие-либо существующие библиотеки, которые позволяют абстрагироваться от таких числовых форматов, чтобы абстрагироваться от различных способов выполнения математических операций, или мне нужно создавать свои собственные?

Я начал кодировать кое-что, что, кажется, работает хорошо, но, как мне кажется, было бы гораздо лучше иметь хорошо протестированную библиотеку, чем изобретать велосипед.

ОТРЕДАКТИРОВАНО, чтобы прояснить ситуацию с контентом из комментария ниже:

Проблема в том, что BigDecimal значительно медленнее, чем double * double и т. д. Нам нужно иметь возможность переключаться между точностью и скоростью. Причина этого в том, что нам нужно иметь возможность запускать быстрые тесты для отладки и перекрестных проверок с реальными данными (которые не обязательно должны быть абсолютно точными), но окончательное моделирование (которое часто занимает от нескольких дней до недель: неприемлемо для отладка) потребует высокой точности. Таким образом, необходимо иметь возможность переключаться по желанию.


person Ricky Cook    schedule 11.11.2011    source источник
comment
Что у тебя за проблемы с плаванием?   -  person zeller    schedule 11.11.2011
comment
Нам нужно иметь возможность переключаться между сверхвысокой скоростью и высокой точностью. Наше приложение будет работать от нескольких дней до нескольких недель, что неприемлемо для простых тестов (не требующих высокой точности). Для получения дополнительной информации см. Мой комментарий Питеру Лоури ниже.   -  person Ricky Cook    schedule 14.11.2011
comment
Я не знаю какой-либо библиотеки произвольной точности для java, которая быстрее, чем apfloat... Или даже любая такая библиотека для java, которая использует числа с плавающей запятой. Обходной путь — использовать целые числа, чем вы можете использовать JScience , а затем разделить на масштаб.   -  person zeller    schedule 14.11.2011
comment
Ну, это не должна быть произвольная точность. Нам нужно всего около 5-10 пунктов точности, но они ДОЛЖНЫ быть гарантированно абсолютно точными. В идеале мне нужна библиотека с фиксированной точкой, но это не тема вопроса. Темой вопроса является библиотека абстракций, которая позволяет переключаться между методами произвольной точности/фиксированной точки/собственными методами расчета (или даже их вариантами).   -  person Ricky Cook    schedule 14.11.2011
comment
Ну, я не знаю такой библиотеки, но, конечно, это не значит, что ее нет. (Но если на самом деле ничего не существует, вы можете реализовать его для себя с помощью шаблона стратегии, например, хотя это немного снижает производительность)   -  person zeller    schedule 14.11.2011
comment
Это именно то, к чему я сейчас стремлюсь, и я также решил открыть исходный код, когда закончу. По сути, это будет оболочка вокруг функциональности BigDecimal/BigInteger, но с возможностью реализации других стратегий для выполнения таких действий, как (в настоящее время реализованных) add, subtract, multiply, divide и pow с фабрикой для создания новых числовых/математических объектов.   -  person Ricky Cook    schedule 14.11.2011
comment
Привет, Рикки, я только что столкнулся с той же проблемой - как твои усилия пошли тогда в 2011 году? :)   -  person vektor    schedule 05.04.2014
comment
Я не могу вспомнить, извините. Я думаю, что нам просто пришлось ускорить симуляции, срезав углы и сделав (иногда неверные) предположения, вместо того, чтобы фактически заниматься математикой (только в тестах, конечно).   -  person Ricky Cook    schedule 07.04.2014


Ответы (1)


double имеет более чем в два раза большую точность, чем float, и обычно не более чем на 10% медленнее. ИМХО, очень редко бывает веская причина использовать float, обычно лучше использовать double или BigDecimal.

person Peter Lawrey    schedule 11.11.2011
comment
Согласен, на двойном фронте. Я начал (глупо) использовать числа с плавающей запятой и был в процессе изменения их всех на двойные. Проблема в том, что BigDecimal значительно медленнее, чем double * double и т. д. Нам нужно иметь возможность переключаться между точностью и скоростью. Причина этого в том, что нам нужно иметь возможность запускать быстрые тесты для отладки и перекрестных проверок с реальными данными, но окончательное моделирование (которое часто занимает от нескольких дней до недель: неприемлемо для отладки) потребует высокой точности. Таким образом, необходимо иметь возможность переключаться по желанию. - person Ricky Cook; 14.11.2011
comment
Тем не менее, мне понравился ваш ответ, поэтому, если не появится ничего лучше, я приму его. - person Ricky Cook; 14.11.2011
comment
Многие операции используют только точность double, поэтому использование float на самом деле медленнее. Где float может иметь небольшой выигрыш, так это в лучшем использовании кеша. Я согласен с тем, что BigDecimal тоже не работает, но если вам нужна точность более 15 цифр, это может быть вашим единственным вариантом. - person Peter Lawrey; 14.11.2011
comment
Ага, в этом суть. Иногда это необходимо, иногда нет. Нам нужно указать, хотим ли мы пожертвовать точностью ради скорости или скоростью ради точности. Сегодня я работал над своей собственной библиотекой абстракций. Пока это работает довольно хорошо, и реализация вычислений с использованием long выглядит примерно в 10 раз быстрее, чем BigDecimal при использовании JIT (хотя это может быть из-за моих ошибочных навыков бенчмаркинга!), и наравне с BigDecimal с включенным флагом -Xint на. Около 10 % накладных расходов при использовании адаптера BigDecimal. - person Ricky Cook; 14.11.2011
comment
Кроме того, указанная библиотека будет выпущена с открытым исходным кодом, поскольку похоже, что нет эквивалента (хотя на данный момент она довольно проста и реализует только небольшое подмножество операций — add, sub, mult, div, pow). - person Ricky Cook; 14.11.2011
comment
double не гарантирует даже 2 точки точности в крайних случаях. Хорошо продемонстрировано в эффективном элементе Java 48. - person zeller; 14.11.2011
comment
Есть способы злоупотреблять double, но использование BigDecimal также может не каждый раз приводить к тому, что вы ожидаете. new BigDecimal(0.1) некоторых удивляет. Короче говоря, это помогает знать, что вы делаете. - person Peter Lawrey; 14.11.2011
comment
@david, поэтому, почему в рамках моей математической реализации я пишу функции для обработки вычислений в длинных числах, умножая десятичное число (так что 300,003 становится 300003 до тех пор, пока не потребуется, когда оно преобразуется обратно). Пока этот метод работает на одном уровне с BigDecimal, когда JIT не используется, и быстрее в 10 раз, когда используется JIT. Единственный существенный недостаток, который я вижу, заключается в том, что при использовании значений в 100000 раз больше, чем вы ожидаете, в конечном итоге получится очень-очень большое число, которое может не уместиться в длинное (окончательное значение будет, но прерывистый расчет не может!) Насколько я понимаю , это точность фиксированной точки? - person Ricky Cook; 14.11.2011
comment
@PeterLawrey new BigDecimal("0.1") или new BigDecimal("" + 0.1)? :) Я никогда раньше не использовал BigDecimal, но я всегда провожу довольно много исследований, когда мои расчеты касаются этого проекта, и модульное тестирование ... обширно, если не сказать больше. - person Ricky Cook; 14.11.2011
comment
@FuzziBear, BigDecimal.valueOf(double) немного эффективнее. - person Peter Lawrey; 14.11.2011