Próbuję użyć BigDecimals w Clojure do modelowania (jeśli to konieczne) dowolnych liczb precyzji. Mam dziwny błąd przy próbie instancji BigDecimal od współczynnika wartości i skalę nieskalowanego:Clojure BigInt nie jest Javą BigInteger
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
Problem polega na tym, że duża liczba całkowita clojure NIE jest obiektem java.math.BigInteger. Nawet (bigint x) nie działa:
user=> (doc bigint)
-------------------------
clojure.core/bigint
([x])
Coerce to BigInt
nil
A przy okazji konstruktor BigInteger nie przyjmuje bezpośrednio wartości liczbowych. Wiem, że mogę również zrobić coś takiego:
user=> (BigDecimal. (BigInteger. (.toByteArray (.unscaledValue 1.31M))) (.scale 1.31M))
1.31M
Moje pytanie brzmi: czy istnieje bardziej idiomatycznych sposób bezpośrednio zarządzać obiektami BigInteger z Clojure? Czy też utknąłem, aby zawinąć wszystko w niestandardowej bibliotece, na przykład:
user=> (defn my-bigint [x] (BigInteger. (.toString x)))
#'user/my-bigint
user=> (my-bigint 131)
131
user=> (BigDecimal. (my-bigint 131) 2)
1.31M
Z góry dziękuję za pomoc!
AKTUALIZACJA: I POTRZEBUJ a BigInteger dla celów serializacji: moim pomysłem jest przechowywanie BigDecimal jako tablicy bajtów i liczby całkowitej. Moim problemem jest to, że w Clojure, jeśli chcę, mogę nie zdać wynik .unscaledValue iz powrotem bo Clojure nie obsługuje BigInteger utworzone z liczb całkowitych (ani zrobić Java, co ma znaczenie):
user=> (BigInteger. 3)
IllegalArgumentException No matching ctor found for class java.math.BigInteger clojure.lang.Reflector.invokeConstructor (Reflector.java:183)
Wywołanie .toString na liczbie jest nieużyteczne dla semantyki serializacji (i bardziej podatne na błędy). Chciałbym wiedzieć, czy w Clojure istnieje idiomatycznych sposób napisać coś takiego:
user=> (bigdec 131N 2)
Nie .movePointLeft (utworzenie dwóch różnych obiektów bez świadczeń), nie .ToString (mam numer, ja go stringify a następnie utworzyć BigInteger, inny numer, z niego?), bez powolnej i pośredniej metody: po prostu BigInteger i wartość skali.
Vinz
zawinąć funkcję z bigdec źródła. –
Rzeczywiście, w tej chwili w mojej głowie było przedstawienie łaty, która może zmodyfikować źródło czaru, aby zaakceptować współczynnik skali (co jest głównym problemem). Jeśli umieścisz to (problem ze skalą i kod źródłowy, który chcesz zmodyfikować) przyjmuję twoją odpowiedź :) (BTW, zaczynam myśleć, że jest to ograniczenie Java API, ale jest to inny temat ...) –
Zaakceptowany mimo wszystko, w końcu twój pomysł obejścia BigInteger nie jest taki zły, otulę go głową! –