Как я понимаю, длинный двойной в C++ фактически использует аппаратную архитектуру (по крайней мере для некоторых архитектур). Делает ли BigDecimal в Java это достаточно для небольших ресурсов?Является ли Java BigDecimal использующим аппаратную архитектуру как длинный двойной в C++?
ответ
ли BigDecimal в Java сделать это для достаточно малых входов?
Нет, и он не мог. Числа с плавающей запятой являются потерями, а каждый BigDecimal
имеет связанную точность и может представлять точно любое число ниже этой точности. Нет «достаточно небольшого ввода», который может быть полезен в виде числа с плавающей запятой, потому что даже если у вас есть значение BigDecimal
, которое может быть представлено точно в нотации с плавающей запятой, вам будет трудно сделать какие-либо сортировка операций по этому значению и поддержание указанной точности.
Иными словами, цель от BigDecimal
- предложить точность, приносящую в жертву скорость. Это работает точно против плавающей точки, которая жертвует точностью в пользу скорости.
Это звучит, как вы спрашиваете, если Java предлагает способ работы с long double
числа размерных чисел с плавающей точкой, и there is not. Из факта, что авторы JDK никогда не чувствовали необходимости добавлять к языку, нельзя сделать вывод.
Подождите, вы говорите, что поплавки и парные разряды не поддерживают определенный уровень точности? У меня создалось впечатление, что стандарт IEEE гарантировал, что стандартные операции над ними (по крайней мере для нормализованных номеров) гарантированно поддерживают уровень точности, близкий (или точно), определенный числом бит (т.е. 32 для float, 64 для двойного). – Daishisan
Числа с плавающей запятой имеют точность, но это не соответствует понятию арифметической точности (например, с точностью до 5 знаков после запятой), о которой мы обычно думаем. Например, невозможно точно представить «0,1» в плавающей точке; под крышками вместо этого используется близкое приближение. Wikipedia переходит к [подробнее] (https://en.wikipedia.org/wiki/Floating_point#Accuracy_problems) об этом, и есть интересный [блог] (http://www.exploringbinary.com/), посвященный в основном обсуждению проблемы с математикой с плавающей запятой. – dimo414
О, я не понимал, что BigDecimal был фактически в базе 10 (несмотря на название). Я просто предположил, что десятичное имя в названии ссылается на то, что оно не может быть целым числом. В этом случае это имеет смысл. – Daishisan
№ BigDecimal не использует любую аппаратную архитектуру. См. Например, конструктор BigDecimal из исходного кода Java.
BigDecimal(BigInteger intVal, long val, int scale, int prec) {
this.scale = scale;
this.precision = prec;
this.intCompact = val;
this.intVal = intVal;
}
В то время как хороший момент это фактически не отвечает на вопрос, потому что JVM может заменить реализацию BigDecimal для конкретных архитектур. Это то, что происходит с «Math», например. Насколько мне известно, ничего подобного не происходит с «BigDecimal», но, глядя на одну конкретную реализацию, она не рассказывает всю историю. – dimo414
@ dimo414 вы можете привести мне пример - JVM может заменить реализацию XXXX для определенных архитектур - чтобы я мог ее прочитать? –
['Math'] (https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html) - канонический пример; эталонная реализация, включенная в ['share'] JDK (http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/java/lang/Math.java), является вероятно * не *, что использует ваш JVM. Точное поведение 'Math' не определено и остается до отдельных реализаций и архитектур. – dimo414
Важнейшим отличием BigDecimal и типичной аппаратной длинной двойной поддержки является радиус с плавающей запятой.
Значение BigDecimal является целым числом, умноженным на десять. Аппаратное обеспечение с плавающей точкой обычно основано на двоичной переменной с плавающей точкой IEEE, и каждое значение представляет собой целое число, умноженное на мощность двух.
Некоторые вычисления, входы которых точно представлены в длинном двойном, имеют результаты, которые имеют большую ошибку округления в длинном двойном, чем в BigDecimal с заданным масштабом. Например, 1 и 10 оба могут быть представлены точно в обоих форматах. Результат деления 1 на 10 может быть представлен точно в BigDecimal со шкалой не менее 1, но не в любом формате radix 2.
Существует, конечно, множество рациональных решений, которые не могут быть представлены точно в любом формате. Рассмотрим 1/3. Даже там BigDecimal получит большую или меньшую ошибку округления, в зависимости от масштаба. Ответ вряд ли будет таким же в длинном двойном и BigDecimal.
Выполнение тестов при каждом вычислении для определения того, получают ли два формата один и тот же ответ, приведет к разрушению любого коэффициента усиления производительности при использовании аппаратного обеспечения.
Уточните ваш вопрос. 'BigDecimal' - это просто класс, который описывает структуру для хранения произвольных длинных чисел. Как он может использовать аппаратную архитектуру? – Andremoniy
И вы знаете: ** аппаратное обеспечение ** Java является виртуальной машиной Java. Но это не помешает JIT сопоставить определенную известную конструкцию (например, объекты BigInteger) с чем-то очень специфичным при создании собственного кода ... – GhostCat
@Andremoniy Я немного смущен вашим вопросом. Длинный двойной в C++ тоже тип, и он явно использует аппаратную архитектуру.Я в основном спрашиваю, делает ли BigDecimal что-то подобное для чисел, которые могут вписываться в 70 бит (что больше, чем 64 в двойном). – Daishisan