2012-05-17 6 views
7

मैं कुछ अजीब जावा व्यवहार को ट्रैक करने की कोशिश कर रहा था। मेरे पास एक सूत्र है जिसमें एक डबल शामिल है, लेकिन एक पूर्णांक उत्तर देने के लिए "गारंटीकृत" है - विशेष रूप से, एक हस्ताक्षरित 32-बिट पूर्णांक (जो, हां, जावा अच्छी तरह से नहीं करता है)। दुर्भाग्य से, मेरे जवाब कभी-कभी गलत थे।जावा पूर्णांक-प्रकार आदिम कास्टिंग प्रकार के MAX_INT पर "कैप्ड" होता है?

आखिरकार मैं इस मुद्दे पाया है, लेकिन व्यवहार अभी भी मेरे लिए बहुत करने के लिए अजीब है: एक long जबकि एक double डाली एक double डाली एक int करने के लिए सीधे एक हस्ताक्षरित पूर्णांक के लिए MAX_INT पर सीमित कर दिया है, कि हैint पर डाला गया मुझे अपेक्षित उत्तर देता है (-1; एक हस्ताक्षरित 32-बिट पूर्णांक का MAX INT हस्ताक्षरित 32-बिट पूर्णांक के रूप में दर्शाया गया है)।

Long is: 4123456789 
Translated to Int is:-171510507 
Long 2 is: 4294967295 
Translated to Int is:-1 
Max UInt as Double: 4.294967295E9 
Max UInt from Double to Long: 4294967295 
Max UInt from Double to Int: 2147483647 
// MAX INT for an unsigned int 
Formula test: 2147483647 
// Binary: all 1s, which is what I expected 
Formula Test with Double Cast: -1 

नीचे दो पंक्तियों वाले मैं समझने की कोशिश कर रहा हूँ कर रहे हैं: जब मैं इस छोटे से कार्यक्रम मैं चलाने

public static void main(String[] args) { 
    // This is the Max Int for a 32-bit unsigned integer 
    double maxUIntAsDouble = 4294967295.00; 
    long maxUintFromDoubleAsLong = (long)maxUIntAsDouble; 
    long maxUintFromDoubleAsInt = (int)maxUIntAsDouble; 
    int formulaTest = (int) (maxUintFromDoubleAsLong * 1.0); 
    int testFormulaeWithDoubleCast = (int)((long) (maxUintFromDoubleAsLong * 1.0)); 
    // This is a more-or-less random "big number" 
    long longUnderTest = 4123456789L; 
    // Max int for a 32-bit unsigned integer 
    long longUnderTest2 = 4294967295L; 
    int intFromLong = (int) longUnderTest; 
    int intFromLong2 = (int) longUnderTest2; 
    System.out.println("Long is: " + longUnderTest); 
    System.out.println("Translated to Int is:" + intFromLong); 
    System.out.println("Long 2 is: " + longUnderTest2); 
    System.out.println("Translated to Int is:" + intFromLong2); 
    System.out.println("Max UInt as Double: " + maxUIntAsDouble); 
    System.out.println("Max UInt from Double to Long: " + maxUintFromDoubleAsLong); 
    System.out.println("Max UInt from Double to Int: " + maxUintFromDoubleAsInt); 
    System.out.println("Formula test: " + formulaTest); 
    System.out.println("Formula Test with Double Cast: " + testFormulaeWithDoubleCast); 
} 

:

मैं एक छोटे से परीक्षण कार्यक्रम में लिखा था। डबल कास्ट मुझे अपेक्षित "-1" देता है; लेकिन सीधी कास्ट मुझे 32-बिट हस्ताक्षरित पूर्णांक के लिए MAX_INT देता है। एक सी ++ पृष्ठभूमि से आ रहा है, मैं समझूंगा कि अगर मुझे अपेक्षित -1 (उर्फ "बेवकूफ कास्टिंग") के बजाय मुझे "विषम संख्या" दी गई है, लेकिन यह मुझे परेशान कर रहा है।

तो, सवाल तो करने के लिए: जावा में इस "उम्मीद" व्यवहार (जैसे किसी भी double डाली एक int के लिए सीधे MAX_INT करने के लिए "छाया हुआ" किया जाएगा) है? क्या किसी भी अप्रत्याशित प्रकार के लिए यह कास्टिंग करता है? मैं उम्मीद करता हूं कि यह short और byte के लिए समान होगा, उदाहरण के लिए; लेकिन फ्लोट करने के लिए एक oversized-double कास्टिंग करते समय 'अपेक्षित व्यवहार' क्या है?

धन्यवाद!

उत्तर

10

यह व्यवहार की उम्मीद है। याद रखें कि जावा में कोई आदिम हस्ताक्षर किए गए लंबे या int प्रकार नहीं हैं, और Java Language Specification (जावा 7) आदिम रूपांतरण को संक्षिप्त करने के लिए (5.1।3) कहता है कि एक बहुत छोटा या बहुत बड़ा "फ़्लोटिंग पॉइंट वैल्यू (चाहे वह डबल या फ्लोट हो) को इंटीग्रल टाइप इंट या लम्बाई का कास्टिंग करेगा, हस्ताक्षर किए गए अभिन्न प्रकारों (जोर खान) के न्यूनतम या अधिकतम मूल्य का उपयोग करेगा:

एक अभिन्न प्रकार टी करने के लिए एक फ्लोटिंग प्वाइंट नंबर की एक संकुचन रूपांतरण दो कदम उठा लेता: पहले चरण में

  1. , फ्लोटिंग प्वाइंट नंबर या तो को एक लंबे, बदल जाती है, तो टी है लंबे, या एक int के लिए, यदि टी बाइट, शॉर्ट, चार, या int है, तो निम्नानुसार है:

    • फ्लोटिंग प्वाइंट नंबर NaN (§4.2.3), रूपांतरण की दिशा में पहला कदम का परिणाम किसी पूर्णांक या लंबी 0.
    • अन्यथा है, अगर फ्लोटिंग प्वाइंट नंबर एक नहीं है, तो अनंतता, फ्लोटिंग-पॉइंट मान को एक पूर्णांक मान V के लिए गोलाकार किया जाता है, आईईईई 754 राउंड-ओर-शून्य मोड (§4.2.3) का उपयोग करके को शून्य की ओर गोल करता है। फिर दो मामले हैं:

      • ए। यदि टी लंबा है, और यह पूर्णांक मान लंबे समय तक प्रदर्शित किया जा सकता है, तो पहले चरण का परिणाम लंबा मूल्य V.
      • बी है। अन्यथा, यह पूर्णांक मान एक पूर्णांक के रूप में प्रतिनिधित्व किया जा सकता है, तो पहला कदम का परिणाम पूर्णांक मूल्य वी
    • अन्यथा है, निम्नलिखित दो मामलों में से एक सत्य होना चाहिए:

      • ए। मान बहुत छोटा होना चाहिए (बड़ी परिमाण या नकारात्मक अनंतता का ऋणात्मक मूल्य), और पहले चरण का परिणाम प्रकार int या लंबे प्रकार का सबसे छोटा प्रतिनिधित्व मूल्य होना चाहिए।
      • बी। मान बहुत बड़ा होना चाहिए (बड़ी परिमाण या सकारात्मक अनंतता का सकारात्मक मूल्य), और पहले चरण का परिणाम प्रकार int या long का सबसे बड़ा प्रतिनिधित्व करने योग्य मान होना चाहिए। *
  2. दूसरे चरण में: * यदि टी पूर्णांक या लंबा है, रूपांतरण के परिणाम पहला कदम का परिणाम है। * यदि टी बाइट, चार, या छोटा है, तो रूपांतरण का परिणाम पहले चरण के परिणाम के टी (§5.1.3) टाइप करने के लिए रूपांतरण को संकुचित करने का परिणाम है।

उदाहरण 5.1.3-1। आदिम रूपांतरण संकुचन

class Test { 
    public static void main(String[] args) { 
     float fmin = Float.NEGATIVE_INFINITY; 
     float fmax = Float.POSITIVE_INFINITY; 
     System.out.println("long: " + (long)fmin + ".." + (long)fmax); 
     System.out.println("int: " + (int)fmin + ".." + (int)fmax); 
     System.out.println("short: " + (short)fmin + ".." + (short)fmax); 
     System.out.println("char: " + (int)(char)fmin + ".." + (int)(char)fmax); 
     System.out.println("byte: " + (byte)fmin + ".." + (byte)fmax); 
    } 
} 

इस कार्यक्रम के उत्पादन का उत्पादन:

long: -9223372036854775808..9223372036854775807 
int: -2147483648..2147483647 
short: 0..-1 
char: 0..65535 
byte: 0..-1 

चार, पूर्णांक के लिए परिणाम, और लंबे समय unsurprising कर रहे हैं, न्यूनतम और प्रकार की अधिकतम प्रदर्शनीय मूल्यों का निर्माण किया।

अंक और संख्यात्मक मानों की परिमाण के बारे में बाइट और कम खोने की जानकारी के परिणाम और सटीकता भी खो देते हैं।परिणाम न्यूनतम और अधिकतम int के निम्न आदेश बिट्स की जांच करके समझा जा सकता है। न्यूनतम int हेक्साडेसिमल, 0x80000000 में है, और अधिकतम int 0x7fffffff है। यह संक्षिप्त परिणाम बताता है, जो इन मानों के कम 16 बिट्स, अर्थात् 0x0000 और 0xffff हैं; यह चार परिणामों को बताता है, जो इन मानों के कम 16 बिट्स हैं, अर्थात् '\ u0000' और '\ uffff'; और यह बाइट परिणाम बताता है, जो इन मानों के कम 8 बिट्स हैं, अर्थात् 0x00 और 0xff।

पहला मामला int formulaTest = (int) (maxUintFromDoubleAsLong * 1.0); इस प्रकार गुणन के माध्यम से एक डबल करने के लिए maxUintFromDoubleAsLong को बढ़ावा देता है और फिर किसी पूर्णांक पर डाले। चूंकि मान एक हस्ताक्षरित पूर्णांक के रूप में प्रतिनिधित्व करने के लिए बहुत बड़ा है, मान 2147483647 (Integer.MAX_VALUE) या 0x7FFFFFFF बन जाता है।

उत्तरार्द्ध मामले का सवाल है:

एक अभिन्न प्रकार टी को एक हस्ताक्षरित पूर्णांक की एक संकुचन रूपांतरण केवल सभी लेकिन n न्यूनतम आदेश बिट्स, जहां n प्रकार का प्रतिनिधित्व करने के लिए बिट की संख्या है को छोड़ देता है टी। संख्यात्मक मूल्य की परिमाण के बारे में की संभावित हानि के अतिरिक्त, इनपुट मान के संकेत से भिन्न होने के परिणामस्वरूप मान का संकेत हो सकता है।

तो int testFormulaeWithDoubleCast = (int)((long) (maxUintFromDoubleAsLong * 1.0)); सबसे पहले maxUintFromDoubleAsLong को दोबारा, लंबे समय तक (अभी भी फिटिंग) और फिर एक int को बढ़ावा देता है। आखिरी कलाकारों में, अतिरिक्त बिट्स को आसानी से गिरा दिया जाता है, जिससे आपको 0xFFFFFFFF मिल जाता है, जो -1 है जब एक हस्ताक्षरित पूर्णांक के रूप में व्याख्या की जाती है।

+0

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

3

यह भाषा का नमूना लिखने का तरीका है। फ़्लोटिंग-पॉइंट को एक पूर्णांक प्रकार में कनवर्ट करना, यदि गंतव्य गंतव्य के लिए बहुत बड़ा है तो अधिकतम मान प्रतिस्थापित किया जाता है। एक पूर्णांक प्रकार से एक छोटे से एक संकीर्ण रूपांतरण में, उच्च-आदेश बिट्स को त्याग दिया जाता है।

देखें JLS 5.1.3. Narrowing Primitive Conversion

तो, शीर्षक में सवाल का जवाब "हाँ"।

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