2015-09-08 5 views
7

मुझे लगता है कि सवाल बहुत सीधी है। लेकिन यहां एक उदाहरण है।यदि परीक्षण लंबे समय तक डबल फिट में संग्रहीत किया जाता है तो परीक्षण कैसे करें? (हां दौर, लेकिन छंटनी नहीं)

नीचे उदाहरण ठीक है। मैं गोल कर सकता हूं और यहां कोई छंटनी नहीं की गई थी।

public static void main(String[] args) { 
    double d = 9.9; 
    long l = (long)d; 
    System.out.println(l); 
} 

आउटपुट: लंबे की सीमा से बाहर

9 

और अब संख्या:

public static void main(String[] args) { 
    double d = 99999999999999999999999999999999.9; 
    long l = (long)d; 
    System.out.println(l); 
} 

आउटपुट:

9223372036854775807 

यह एक मेरे लिए परेशानी पैदा। मैं पूरी तरह से अलग संख्या के साथ काम जारी नहीं रख सकता। मुझे एक त्रुटि या अपवाद मिलेगा।

क्या जावा में इसका पता लगाने का कोई तरीका है?

उत्तर

12

आप Long.MIN_VALUE और Long.MAX_VALUE के साथ तुलना कर सकते हैं:

public static boolean fitsLong(double d) { 
    return d >= Long.MIN_VALUE && d < Long.MAX_VALUE; 
} 

कुछ अधिक sofisticated दृष्टिकोण BigDecimal उपयोग करने के लिए है:

double value = 1234567.9; 
long l = BigDecimal.valueOf(value) 
        .setScale(0, RoundingMode.HALF_EVEN) 
        .longValueExact(); // 1234568 

double value = 99999999999999999999999999999999.9; 
long l = BigDecimal.valueOf(value) 
        .setScale(0, RoundingMode.HALF_EVEN) 
        .longValueExact(); // ArithmeticException 

इस तरह से आप कैसे राउंडिंग किया जाता है नियंत्रित कर सकते हैं।

आप पूछ सकते हैं, fitsLong: d < Long.MAX_VALUE में सख्त असमानता क्यों है। दरअसल ऐसा इसलिए है क्योंकि Long.MAX_VALUE को स्वयं को डबल नंबर के रूप में प्रदर्शित नहीं किया जा सकता है। जब आप (double)Long.MAX_VALUE डालते हैं, तो इसका प्रतिनिधित्व करने के लिए double प्रकार में पर्याप्त सटीकता नहीं है, इसलिए निकटतम प्रतिनिधित्व योग्य मान चुना गया है जो 9223372036854775808.0 (Long_MAX_VALUE+1.0) है। तो यह d <= Long.MAX_VALUE था यह true संख्या के लिए वापस आ जाएगा जो वास्तव में इस तुलना में थोड़ा बड़ा है Long.MAX_VALUE निरंतर डबल प्रकार के लिए प्रचारित किया जाता है। दूसरी तरफ को double प्रकार में बिल्कुल दर्शाया जा सकता है, इस प्रकार हमारे पास >= है।

इसके अलावा यह दिलचस्प है क्यों निम्नलिखित काम करता है:

double value = -9223372036854775809.9; // Long.MIN_VALUE-1.9 
System.out.println(fitsLong(value)); // returns true 

क्योंकि आप वास्तव में Long.MIN_VALUE से कुछ भी घटाना नहीं था कि। देखें:

double d1 = Long.MIN_VALUE; 
double d2 = -9223372036854775809.9; 
System.out.println(d1 == d2); // true 

डबल परिशुद्धता -9223372036854775808 और -9223372036854775809.9 के बीच अंतर करने के लिए पर्याप्त नहीं है, इसलिए यह वास्तव में एक ही डबल संख्या है। संकलन के दौरान इसे बाइनरी रूप में परिवर्तित कर दिया जाता है, और इन दो संख्याओं के लिए बाइनरी रूप समान होता है। इस प्रकार संकलित प्रोग्राम होने पर आप इस बात को अलग नहीं कर सकते कि -9223372036854775808 या -9223372036854775809.9 स्रोत कोड में था या नहीं।

अगर आपको लगता है कि यह अभी भी मुद्दा है, String से BigDecimal का निर्माण:

long l = new BigDecimal("-9223372036854775808.2") 
        .setScale(0, RoundingMode.HALF_EVEN) 
        .longValueExact(); // ok, -9223372036854775808 

long l = new BigDecimal("-9223372036854775808.9") 
        .setScale(0, RoundingMode.HALF_EVEN) 
        .longValueExact(); // ArithmeticException 
+0

पहले समाधान के लिए) वास्तव में आप नहीं कर सकते। मैंने कोशिश की और यह काम नहीं करेगा। उदाहरण के लिए 922337203685477580 9.9 मान का प्रयास करें जो 2.9 तक Long.MAX_VALUE बढ़ाया गया है। यह सफल हो जाएगा। – arenaq

+0

आप सही हैं, लेकिन जब मैं दोनों समाधानों के लिए 9 223372036854775807.0 का उपयोग करता हूं। FitsLong मुझे सच देता है और BigDecimal एक अपवाद फेंकता है। वह डबल मान अपरिवर्तित हो सकता है, लेकिन कम से कम समाधानों में से एक गलत होना चाहिए। – arenaq

+1

@arenaq डबल में 53 बिट्स मंथिसा है और यह केवल 15-17 अंकों के लिए सटीक हो सकता है। 9223372036854775809.9 और 9 223372036854775807 http://stackoverflow.com/q/588004/995714 –

1

आप एक int या long करने के लिए एक चल बिन्दु प्रकार डाली, तो परिणाम है या तो निकटतम पूर्णांक (की ओर गोलाई शून्य), या MIN_VALUE या MAX_VALUEint या long के लिए। JLS 5.1.3 देखें।

इसलिए, एक विकल्प टाइपकास्ट करना होगा और उसके बाद उचित MIN_VALUE या MAX_VALUE के लिए परीक्षण करना होगा।

ध्यान दें कि Long.MAX_VALUE9223372036854775807 है ... जो आपके परीक्षण कार्यक्रम आउटपुट की संख्या है!

(हालांकि, यह आप byte, char या short करने के लिए एक चल बिन्दु प्रकार कास्ट कर रहे हैं, तो काम नहीं करता। विवरण के लिए ऊपर दिए गए लिंक देखें।)

संबंधित मुद्दे