У меня есть куча чисел с плавающей запятой (Java удваивается), большинство из которых очень близко к 1, и мне нужно умножить их вместе как часть более крупного вычисления. Мне нужно сделать это много .
Проблема в том, что в то время как у парных символов Java нет проблем с таким числом, как:
0.0000000000000000000000000000000001 (1.0E-34)
они не могут представлять что-то вроде:
1.0000000000000000000000000000000001
Следовательно, из-за этого я быстро теряю точность (кажется, что для двойников Java предел составляет около 1,000000000000001).
Я рассмотрел просто сохранение чисел с вычитаемым 1, поэтому, например, 1,0001 будет сохранено как 0,0001 - но проблема в том, что для их умножения снова нужно добавить 1, и в этот момент я теряю точность.
Чтобы решить эту проблему, я мог бы использовать BigDecimals для выполнения вычислений (преобразовать в BigDecimal, добавить 1,0, затем умножить), а затем преобразовать обратно в удвоения, но у меня есть серьезные опасения по поводу последствий для производительности.
Может кто-нибудь увидеть способ сделать это, избегая использования BigDecimal?
Правка для ясности : Это для крупномасштабного совместного фильтра, который использует алгоритм оптимизации градиентного спуска. Точность является проблемой, потому что часто фильтр совместной работы имеет дело с очень маленькими числами (например, вероятность того, что человек нажмет на объявление для продукта, которое может быть 1 на 1000 или 1 на 10000).
Скорость - это проблема, потому что фильтр совместной работы должен быть обучен на десятках миллионов точек данных, если не больше.