2013-08-02 6 views
11

Sto cercando indicazioni su quando utilizzare Clojure BigInt rispetto a Java BigInteger in Clojure. Entrambi funzionano perfettamente e presumo che la ragione principale per utilizzare BigInt sia quella di sfruttare operatori come + e =, ai quali è necessario accedere tramite i metodi di istanza Java .add e .equals, ad esempio. Ma ci sono pochi operatori, come ad esempio isProbablePrime, a cui posso accedere solo da BigInteger.casi d'uso per BigInt contro BigInteger in Clojure

Sembra abbastanza facile passare da BigInt a BigInteger o viceversa, ma la presenza di entrambi rende i casi d'uso poco chiari per me. La mia reazione istintiva è semplicemente quella di restare con BigInteger in assenza di criteri chiari, dal momento che alcuni degli usi suggeriti sembrano non funzionare. Da clojuredocs here:

user=> (def x (bigint 97)) 
user=> (.isProbablePrime x 1) 
IllegalArgumentException No matching method found: isProbablePrime for class  
clojure.lang.BigInt clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:53) 
+1

Dopo aver dato un'occhiata al codice sorgente di BigInt (https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/BigInt.java) sembra che un BigInt contenga entrambi un java.math.Bigint e un lungo. Sulla pagina web Clojure si dice che i BigInts mantengono il loro tipo in tutte le operazioni. Considerando che puoi lanciare facilmente con .toBigInteger e .fromBigInteger nel caso in cui tu voglia usare metodi come isProbablePrime, e anche considerando che non è facile costruire come java.math.BigInteger, mi limiterei a bigint e cast avanti e indietro se necessario (BigInts farlo da sé ad esempio in .add). –

+0

In realtà 'clojure.lang.BigInt/fromBigInteger'; Ho aggiunto un esempio qui http://clojuredocs.org/clojure_core/clojure.core/bigint –

+0

Usavate i numeri di Lucas per caso? – Carcigenicate

risposta

22

In "Clojure Programming" di C. Emerick et. al., p.428, c'è un argomento nella barra laterale, "Perché Clojure ha una propria classe BigInt quando Java ne fornisce già una in BigInteger?"

Si noti due motivi per preferire BigInt a Java BigInteger. Innanzitutto, l'implementazione di .hashCode di quest'ultima è incoerente con quella di Long (lo stesso numero espresso in ciascun tipo restituisce un valore hash diverso). Questo generalmente non è quello che vuoi quando confronti valori equivalenti in es. mappe di hash.

L'altro motivo è che BigInt s sono ottimizzati per utilizzare tipi primitivi quando possibile, quindi le prestazioni dovrebbero essere migliori per molti casi.

Vorrei utilizzare i tipi numerici di Clojure a meno che non si abbia una buona ragione per non farlo (l'utilizzo di .isProbablePrime suggerisce che si potrebbe avere una ragione sufficiente).

+1

Grazie per l'eccellente risposta. Dovrebbero scrivere queste cose nelle docstring. –

+3

Penso che la continuità di 'hash-code' e altri operatori come' range' sia un motivo sufficiente per il bias di 'BigInt'. Posso creare una piccola libreria di operazioni di bridging per cose come '.isProbablePrime'. Quella strategia mi darà una biblioteca più piccola in generale, perché in alternativa, stavo iniziando a essere risucchiato a scrivere un'intera libreria matematica su 'BigInteger', ad es.' Big-range', 'big-le', ecc. –