Estoy tratando de usar BigDecimals en Clojure para modelar (si es necesario) números de precisión arbitrarios. Tengo un extraño error al intentar crear una instancia de un BigDecimal partir de un valor y factor de escala sin escala:Clojure BigInt no es Java 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
El problema aquí es que el clojure entero grande no es un objeto java.math.BigInteger. Even (bigint x) no funciona:
user=> (doc bigint)
-------------------------
clojure.core/bigint
([x])
Coerce to BigInt
nil
Y, por cierto, el constructor de BigInteger no acepta valores numéricos directamente. Sé que también podría hacer algo como:
user=> (BigDecimal. (BigInteger. (.toByteArray (.unscaledValue 1.31M))) (.scale 1.31M))
1.31M
Mi pregunta es: ¿hay una manera más directa idiomática de administrar objetos BigInteger de Clojure? O estoy atrapado para envolver todo en una biblioteca personalizada, como:
user=> (defn my-bigint [x] (BigInteger. (.toString x)))
#'user/my-bigint
user=> (my-bigint 131)
131
user=> (BigDecimal. (my-bigint 131) 2)
1.31M
Gracias de antemano por la ayuda!
ACTUALIZACIÓN: I NECESIDAD un BigInteger para fines de serialización: mi idea es almacenar un BigDecimal como un conjunto de bytes y un número entero. Mi problema es que en Clojure, si quiero, no puedo pasar el resultado de .unscaledValue de ida y vuelta porque Clojure no maneja BigInteger creado a partir de los números enteros (tampoco lo hacen en Java, por lo que importa):
user=> (BigInteger. 3)
IllegalArgumentException No matching ctor found for class java.math.BigInteger clojure.lang.Reflector.invokeConstructor (Reflector.java:183)
Una llamada a .toString en el número no es útil para la semántica de la serialización (y es más propensa a errores). Me gustaría saber si en Clojure hay una forma idiomática para escribir algo como:
user=> (bigdec 131N 2)
Sin .movePointLeft (creación de dos objetos diferentes, sin beneficios), sin .toString (no tengo un número, que se stringify y luego crear un BigInteger, otro número, ¿no?), ningún método lento e indirecto: simplemente BigInteger y valor de escala.
Vinz
envolver una función con fuente bigdec. –
De hecho mi pensamiento en este momento era enviar un parche que modifica ligeramente la fuente de clojura para aceptar el factor de escala (que es el problema principal). Si pones esto (el problema del factor de escala y el código fuente a modificar), aceptaré tu respuesta :) (Por cierto, estoy empezando a pensar que esto es una limitación de la API de Java, pero es otro tema ...) –
¡Aceptado de todos modos, al final tu idea de pasar por alto a BigInteger no es tan mala, la voy a entender! –