Sto cercando di utilizzare BigDecimals in Clojure per modellare (se necessario) numeri di precisione arbitrari. Ho un errore di strano quando si tenta di creare un'istanza di un BigDecimal da un fattore di scala di valore e non in scala:Clojure BigInt non è 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
Il problema qui è che il grande numero intero clojure non è un oggetto java.math.BigInteger. Anche (bigint x) non funziona:
user=> (doc bigint)
-------------------------
clojure.core/bigint
([x])
Coerce to BigInt
nil
E a proposito BigInteger costruttore non accetta direttamente i valori numerici. So che potrei anche fare qualcosa di simile:
user=> (BigDecimal. (BigInteger. (.toByteArray (.unscaledValue 1.31M))) (.scale 1.31M))
1.31M
La mia domanda è: esiste un modo più idiomatico di gestire direttamente gli oggetti BigInteger da Clojure? O sono bloccato per avvolgere tutto in una libreria personalizzata, come:
user=> (defn my-bigint [x] (BigInteger. (.toString x)))
#'user/my-bigint
user=> (my-bigint 131)
131
user=> (BigDecimal. (my-bigint 131) 2)
1.31M
Grazie in anticipo per l'aiuto!
UPDATE: Ho BISOGNO un BigInteger a fini di serializzazione: la mia idea è quella di memorizzare un BigDecimal come un array di byte e un intero. Il mio problema è che in Clojure, se voglio, non posso passare il risultato di .unscaledValue avanti e indietro perche' Clojure non gestisce BigInteger creato da numeri interi (né fare Java, per quello che conta):
user=> (BigInteger. 3)
IllegalArgumentException No matching ctor found for class java.math.BigInteger clojure.lang.Reflector.invokeConstructor (Reflector.java:183)
Una chiamata a .toString sul numero non è utile per la semantica della serializzazione (e più incline agli errori). Vorrei sapere se in Clojure c'è un modo idiomatico per scrivere qualcosa di simile:
user=> (bigdec 131N 2)
No .movePointLeft (creazione di due oggetti diversi, senza benefici), non .toString (Ho un certo numero, mi stringa i essa e quindi creare un BigInteger, un altro numero, da esso?), nessun metodo lento e indiretto: semplicemente BigInteger e valore di scala.
Vinz
avvolgere una funzione con la fonte bigdec. –
In effetti il mio pensiero al momento era di presentare una patch che modifica leggermente la fonte del clojure per accettare il fattore di scala (che è il problema principale). Se metti questo (il problema del fattore di scala e il codice sorgente da modificare) accetterò la tua risposta :) (A proposito, sto iniziando a pensare che questa è una limitazione dell'API Java, ma è un altro argomento ...) –
Accettato comunque, alla fine la tua idea di bypassare BigInteger non è poi così male, mi abbraccerò! –