कैसे पता चलेगा कि बिगडेक्मल वास्तव में फ्लोट या डबल में बदल सकता है?


10

BigDecimalदोषरहित रूपांतरण की गारंटी देने के लिए कक्षा के पास कुछ उपयोगी विधियाँ हैं:

  • byteValueExact()
  • shortValueExact()
  • intValueExact()
  • longValueExact()

हालांकि, तरीके floatValueExact()और doubleValueExact()मौजूद नहीं हैं।

मैंने विधियों के लिए OpenJDK स्रोत कोड पढ़ा floatValue()और doubleValue()। दोनों क्रमशः Float.parseFloat()और Double.parseDouble(), जो सकारात्मक या नकारात्मक अनंत लौट सकते हैं, पर वापस आते हैं। उदाहरण के लिए, 10,000 9 के एक तार को पार्स करने से सकारात्मक अनंत लौट आएगा। जैसा कि मैं समझता हूं, BigDecimalअनंत की एक आंतरिक अवधारणा नहीं है। इसके अलावा, 100 9 नंबर के पत्तों की एक स्ट्रिंग को पार्स करने के रूप में doubleदेता है 1.0E100, जो अनंत नहीं है, लेकिन सटीक खो देता है।

एक उचित कार्यान्वयन floatValueExact()और क्या है doubleValueExact()?

मैं एक के बारे में सोचा doubleसमाधान के संयोजन से BigDecimal.doubleValue(), BigDecial.toString(), Double.parseDouble(String)और Double.toString(double), लेकिन यह गंदा लग रहा है। मैं यहाँ पूछना चाहता हूँ क्योंकि वहाँ (एक!) एक सरल समाधान होना चाहिए।

स्पष्ट होने के लिए, मुझे उच्च प्रदर्शन समाधान की आवश्यकता नहीं है।


7
मुझे लगता है कि आप डबल में बदल सकते हैं, फिर बिगडेसिमल में डबल को बदल सकते हैं, और देख सकते हैं कि क्या आप समान मूल्य प्राप्त करते हैं। सुनिश्चित नहीं है कि उपयोग का मामला क्या है। यदि आप युगल का उपयोग करते हैं, तो आप पहले से ही गैर-सटीक मान रखना स्वीकार करते हैं। यदि आप सटीक मान चाहते हैं, तो BigDecimal के साथ बने रहें।
जेबी निज़ेट

जवाबों:


6

से पढ़ने डॉक्स , सभी इसके साथ करता वेरिएंट एक अंश भाग के होने की जाँच करने के लिए है या यदि मान सांख्यिक प्रकार के लिए बहुत बड़ा है और अपवाद फेंक देते हैं। numTypeValueExact

से संबंधित floatValue() और doubleValue(), एक समान अतिप्रवाह जांच की जा रही है, लेकिन एक अपवाद को फेंकने के बजाय, यह रिटर्न Double.POSITIVE_INFINITYया Double.NEGATIVE_INFINITYडबल्स के लिए और Float.POSITIVE_INFINITYया Float.NEGATIVE_INFINITYफ्लोट्स के लिए।

इसलिए exactफ्लोट और डबल के तरीकों का सबसे उचित (और सरल) कार्यान्वयन , केवल यह जांचना चाहिए कि रूपांतरण वापस आता है POSITIVE_INFINITYया नहीं NEGATIVE_INFINITY


इसके अलावा , याद रखें कि BigDecimalकि का उपयोग कर से आता है परिशुद्धता की कमी को संभालने के लिए डिजाइन किया गया था floatयाdouble बड़े अपरिमेय के लिए , इसलिए @JB निज़ेट ने टिप्पणी की , एक और चेक जिसे आप ऊपर जोड़ सकते हैं doubleया देखने के लिए floatवापस बदलना होगा BigDecimalकि क्या आप अभी भी मिलते हैं एक ही मूल्य। यह साबित करना चाहिए कि रूपांतरण सही था।

यहाँ इस तरह के एक विधि के लिए इस तरह दिखेगा floatValueExact():

public static float floatValueExact(BigDecimal decimal) {
    float result = decimal.floatValue();
    if (!Float.isInfinite(result)) {
        if (new BigDecimal(String.valueOf(result)).compareTo(decimal) == 0) {
            return result;
        }
    }
    throw new ArithmeticException(String.format("%s: Cannot be represented as float", decimal));
}

उपरोक्त के compareToबजाय का उपयोग equalsजानबूझकर किया जाता है ताकि चेक के साथ बहुत सख्त न हो। equalsकेवल तब ही सत्य का मूल्यांकन करेगा जब दो BigDecimalवस्तुओं का समान मान और स्केल (दशमलव के अंश वाले भाग का आकार) compareToहोगा , जबकि इस अंतर की अनदेखी तब होगी जब इससे कोई फर्क नहीं पड़ता। उदाहरण के लिए 2.0बनाम 2.00


बहुत चालाक। वास्तव में मुझे क्या चाहिए! नोट: आप भी उपयोग करना चाहते हैं Float.isFinite()या कर सकते हैं Float.isInfinite(), लेकिन यह वैकल्पिक है। :)
केविनरपे

3
आपको समतुल्यता से तुलना करना पसंद करना चाहिए, क्योंकि BigDecimal में बराबर () 2.0 और 2.00 को अलग-अलग मानों के रूप में मानेंगे।
जेबी निज़ेट

मान जो फ्लोट के रूप में ठीक से दर्शाए नहीं जा सकते, वे काम नहीं करेंगे। उदाहरण: 123.456f। मुझे लगता है कि यह 32-बिट फ्लोट और 64-बिट डबल के बीच महत्व (मंटिसा) के विभिन्न आकार के कारण है। अपने उपरोक्त कोड में, मैं के साथ बेहतर परिणाम प्राप्त: if (new BigDecimal(result, MathContext.DECIMAL32).equals(decimal)) {। क्या यह एक उचित बदलाव है ... या क्या मैं फ़्लोटिंग पॉइंट वैल्यूज़ के एक और कोने के मामले को याद कर रहा हूँ?
केविनरपे

1
@kevinarpe - 123.456fवैचारिक रूप से आपके 1.0E100 उदाहरण के समान है। यह मुझे चौंकाता है कि अगर आपको यह जांचने की आवश्यकता है कि बिगडेसीमल -> बाइनरी फ्लोटिंग पॉइंट से रूपांतरण सटीक है, तो यह समस्या है; अर्थात रूपांतरण पर चिंतन नहीं किया जाना चाहिए।
स्टीफन सी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.