2012-06-11 9 views
7

मैं क्लोजर में मॉडल (यदि आवश्यक हो) मनमाने ढंग से सटीक संख्याओं के लिए BigDecimals का उपयोग करने की कोशिश कर रहा हूं।क्लोजर बिगइंट जावा बिगइंटर

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 वस्तु नहीं है: मैं जब मैं एक बगैर माप का मूल्य और पैमाने कारक से एक BigDecimal का दृष्टांत करने की कोशिश एक अजीब त्रुटि की है। यहां तक ​​कि (bigint एक्स) काम नहीं करता है:

user=> (doc bigint) 
------------------------- 
clojure.core/bigint 
([x]) 
    Coerce to BigInt 
nil 

और जिस तरह से BigInteger निर्माता सीधे संख्यात्मक मान स्वीकार नहीं करता। मैं जानता हूँ कि मैं भी कुछ ऐसा कर सकता है:

user=> (BigDecimal. (BigInteger. (.toByteArray (.unscaledValue 1.31M))) (.scale 1.31M)) 
1.31M 

मेरे सवाल यह है: वहाँ सीधे का एक और अधिक मुहावरेदार रास्ता Clojure से BigInteger वस्तुओं का प्रबंधन है? या मैं कस्टम लाइब्रेरी में सब कुछ लपेटने के लिए फंस गया हूं, जैसे:

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 क्रमशः प्रयोजनों के उद्देश्यों के लिए एक बिगइन्टर की आवश्यकता है: मेरा विचार एक बिगडिमल को बाइट सरणी और एक पूर्णांक के रूप में स्टोर करना है। मेरे समस्या यह है कि Clojure में, अगर मैं चाहता हूँ, मुझे .unscaledValue का परिणाम आगे और पीछे पारित नहीं हो सकता क्योंकि Clojure का क्या करता है नहीं BigInteger पूर्णांकों से बनाए गए (न करना जावा, यह महत्वपूर्ण कार्यों के लिए) है:

user=> (BigInteger. 3) 
IllegalArgumentException No matching ctor found for class java.math.BigInteger clojure.lang.Reflector.invokeConstructor (Reflector.java:183) 

नंबर पर .toString पर कॉल करने के लिए serialization (और अधिक त्रुटि प्रवण) के अर्थशास्त्र के लिए अनुपयोगी है।

user=> (bigdec 131N 2) 

नहीं .movePointLeft (लाभ के बिना दो विभिन्न वस्तुओं के निर्माण), कोई .toString (मैं एक संख्या है, मैं इसे stringify: मैं अगर Clojure में वहाँ एक मुहावरेदार रास्ता की तरह कुछ लिखने के लिए जानना चाहते हैं और फिर बिगइंटर, एक और नंबर, इससे बनाते हैं?), कोई धीमी और अप्रत्यक्ष विधि नहीं: केवल सादा बिगइंटर और स्केल मान।

Vinz

+0

bigdec स्रोत के साथ एक समारोह लपेटो। –

+0

वास्तव में इस समय मेरा विचार एक पैच जमा करना था जो क्लोजर स्रोत को स्केल फैक्टर (जो मुख्य समस्या है) स्वीकार करने के लिए मामूली रूप से संशोधित करता है। यदि आप इसे डालते हैं (स्केल कारक समस्या और स्रोत कोड को संशोधित करने के लिए) मैं आपका जवाब स्वीकार करूंगा :) (बीटीडब्ल्यू, मुझे लगता है कि यह जावा एपीआई की एक सीमा है, लेकिन यह एक और विषय है ...) –

+0

वैसे भी स्वीकृत, अंत में BigInteger को छोड़ने का आपका विचार बुरा नहीं है, मैं अपने सिर को इसके चारों ओर लपेटूंगा! –

उत्तर

8
=> (type (.unscaledValue 1.31M)) 
java.math.BigInteger 

=> (type (biginteger 131)) 
java.math.BigInteger 

=> (BigDecimal. (biginteger 131) 2) 
1.31M 
+0

यह बेहतर है। –

+0

दरअसल, और यह सही जवाब है। मैं 'स्वीकृत उत्तर ध्वज' ले जा रहा हूं। –

+0

https://clojuredocs.org/clojure.core/biginteger – tar

4
user=> (.movePointLeft (bigdec 131) 2) 
1.31M 
user=> (.movePointLeft (bigdec 131N) 2) 
1.31M 

user=> (source bigdec) 
(defn bigdec 
    "Coerce to BigDecimal" 
    {:tag BigDecimal 
    :added "1.0" 
    :static true} 
    [x] (cond 
     (decimal? x) x 
     (float? x) (. BigDecimal valueOf (double x)) 
     (ratio? x) (/ (BigDecimal. (.numerator x)) (.denominator x)) 
     (instance? BigInteger x) (BigDecimal. ^BigInteger x) 
     (number? x) (BigDecimal/valueOf (long x)) 
     :else (BigDecimal. x))) 
+0

दुर्भाग्यवश, मुझे बाइट प्रारूप को एक प्रभावी तरीके से स्टोर करने की आवश्यकता है, इसलिए मुझे क्रमबद्ध करने के लिए एकल बाइट की आवश्यकता है। BigInteger.toByteArray और स्केल के लिए एक पूर्णांक के साथ मैं सही हूं, एक स्ट्रिंग में धारावाहिक होने के लिए 131 एन के साथ मैं नहीं हूं! –

0

मुझे यह पसंद थोड़ा बेहतर:

(-> 131M (.movePointLeft 2)) 
+0

मैं इस सवाल को स्पष्ट कर रहा हूं, 'क्योंकि आवश्यकता को समझ में नहीं आता है ... :) –

+0

बीटीडब्ल्यू, मुझे थ्रेश ऑपरेटर पसंद है;) –