Я пытаюсь использовать BigDecimals в Clojure для моделирования (при необходимости) чисел произвольной точности. У меня есть странная ошибка, когда я пытаюсь создать экземпляр BigDecimal из немасштабированного значения и масштабного коэффициента:
user=> 1.31M
1.31M (OK)
user=> (class 1.31M)
java.math.BigDecimal (OK)
user=> (.unscaledValue 1.31M)
131 (OK)
user=> (.scale 1.31M)
2 (OK)
user=> (.movePointLeft (BigDecimal. 131) 2)
1.31M (OK)
user=> (BigDecimal. (BigInteger. "131") 2)
1.31M
user=> (BigDecimal. 131N 2) (WRONG!!!)
IllegalArgumentException No matching ctor found for class java.math.BigDecimal clojure.lang.Reflector.invokeConstructor (Reflector.java:183)
user=> (BigDecimal. (BigInteger. "131") 2)
1.31M
Проблема здесь в том, что большое целое число clojure НЕ является объектом java.math.BigInteger. Даже (bigint x) не работает:
user=> (doc bigint)
-------------------------
clojure.core/bigint
([x])
Coerce to BigInt
nil
И, кстати, конструктор BigInteger напрямую не принимает числовые значения. Я знаю, что мог бы также сделать что-то вроде:
user=> (BigDecimal. (BigInteger. (.toByteArray (.unscaledValue 1.31M))) (.scale 1.31M))
1.31M
Мой вопрос: есть ли более идиоматический способ непосредственного управления объектами BigInteger из Clojure? Или я застрял, чтобы обернуть все в пользовательскую библиотеку, например:
user=> (defn my-bigint [x] (BigInteger. (.toString x)))
#'user/my-bigint
user=> (my-bigint 131)
131
user=> (BigDecimal. (my-bigint 131) 2)
1.31M
Заранее спасибо за помощь!
ОБНОВЛЕНИЕ: I НУЖЕНBigInteger для целей сериализации: Моя идея состоит в том, чтобы хранить BigDecimal в виде массива байтов и целого числа. Моя проблема в том, что в Clojure, если я хочу, я не могу передать результат .unscaledValue туда и обратно' потому что Clojure не обрабатывает BigInteger, созданный из Integers (как и Java, что имеет значение):
user=> (BigInteger. 3)
IllegalArgumentException No matching ctor found for class java.math.BigInteger clojure.lang.Reflector.invokeConstructor (Reflector.java:183)
Вызов .toString на номере бесполезен для семантики сериализации (и более подвержен ошибкам). Я хотел бы знать, есть ли в Clojure идиоматический способ написать что-то вроде:
user=> (bigdec 131N 2)
Нет .movePointLeft (создание двух разных объектов без преимуществ), нет .toString (у меня есть число, я нанизываю его, а затем создаю BigInteger, другое число, из него?), нет медленного и косвенного метода: просто просто BigInteger и масштабное значение.
Vinz