2013-07-13 5 views
12

मैंने जावा में थोड़ा शिकारी-शिकार सिमुलेशन लिखा है। यहां तक ​​कि अगर नियम काफी जटिल होते हैं और एक अराजक प्रणाली में समाप्त इस्तेमाल तकनीक सरल हैं:जावा निर्धारित नहीं है?

  • arithmetics और बुनियादी डेटा प्रकार
  • कोई बाहरी पुस्तकालयों
  • कोई बाहरी सिस्टम शामिल किए गए हैं पर निर्णय
  • कोई संगामिति होता

तो मैंने सोचा कि जब साथ प्रणाली आरंभ वर्तमान समय या तिथि का कोई उपयोग नहीं समान पैरामीटर को समान परिणामों को आउटपुट करना चाहिए, लेकिन ऐसा नहीं है और मुझे आश्चर्य है कि क्यों।

उस पर कुछ विचार: मेरा आवेदन Random एस का उपयोग करता है, लेकिन उस परीक्षण के लिए मैं उन्हें सभी को एक दिए गए मान के साथ शुरू करता हूं, इसलिए मेरी समझ में उन्हें प्रत्येक क्रम में एक ही आउटपुट के लिए बनाना चाहिए।

मैं Set एस के माध्यम से पुनरावृत्त कर रहा हूं, और मुझे पता है कि ऑर्डर Set पुनरावृत्त नहीं है। लेकिन मुझे कोई कारण नहीं दिख रहा है कि एक Set जो एक ही क्रम में भरा हुआ है, उसी मान के साथ कई रनों में अलग व्यवहार करना चाहिए। क्या यह?

मैं float एस का उपयोग कर रहा हूं। डेटाटाइप जहां 1 + 1 = 1.99 99 99 99 99725 हमेशा मुझे संदेह करते हैं, लेकिन अगर मेरा व्यवहार मेरे लिए अजीब है, तो यह हमेशा एक ही अजीब होना चाहिए। यही है ना

कचरा संग्रह निर्धारक नहीं है, लेकिन जब तक मैं विनाशकों पर भरोसा नहीं करता हूं, मुझे सुरक्षित होना चाहिए।

जैसा ऊपर बताया गया है, उपयोग में वास्तविक समय के आधार पर कोई सहमति नहीं है और कोई डेटाटाइप नहीं है।

मैं उस व्यवहार को एक साधारण उदाहरण में पुन: उत्पन्न नहीं कर सकता। लेकिन मेरे कोड के माध्यम से जा रहा है, मैं कुछ भी नहीं देख सकता जो अप्रत्याशित हो सकता है। तो क्या मेरी गलत धारणाएं गलत हैं? कोई विचार जो मैं खो सकता था?

यहाँ मेरी मान्यताओं को सत्यापित करने के लिए एक परीक्षण है:

public static void main(String[] args) { 
    Random r = new Random(1); 
    Set<Float> s = new HashSet<Float>(); 
    for (int i = 0; i < 1000000; i++) { 
     s.add(r.nextFloat()); 
    } 

    float ret = 1; 
    int cnt = 0; 
    for (Float f : s) { 
     float multiply = 0.3f; 
     if (cnt++ % 2 == 0) { 
      multiply = 0.7f; 
     } 
     float f2 = (f * multiply); 
     ret += f2; 
    } 

    System.out.println(ret); 
} 

यह 242455.25 में हमेशा परिणाम मेरे लिए।

+1

समय समारोह? – Mysticial

+1

जब आप कहते हैं कि आप अपना यादृच्छिक डेटा प्रारंभ करते हैं, तो क्या आपका मतलब है कि आप बीज का उपयोग करते हैं? – tjameson

+0

यह दिलचस्प लगता है। क्या हम आपके कोड पर नजर डालेंगे? – kol

उत्तर

20

आप जावा में एक निर्धारिक कार्यक्रम लिख सकते हैं। आपको केवल गैर-निर्धारणा के संभावित स्रोतों को खत्म करने की आवश्यकता है।

यह जानना मुश्किल है कि आपके वास्तविक कोड को देखे बिना और दृढ़ संकल्प के ठोस सबूत के बिना गैर-निर्धारणवाद क्या हो सकता है।

ऐसी कई लाइब्रेरी विधियां हैं जो संभावित रूप से गैर-निर्धारक व्यवहार के स्रोत हो सकती हैं ... आप उनका उपयोग कैसे करते हैं इसके आधार पर।

उदाहरण के लिए, Object.hashcode() (पहली बार इसे किसी उदाहरण पर कहा जाता है) द्वारा लौटाया गया मूल्य गैर-निर्धारक है। और यह हैशिंग का उपयोग करने वाली किसी भी पुस्तकालय के माध्यम से घिरा हुआ है। यह निश्चित रूप से उस आदेश को प्रभावित कर सकता है जिसमें HashSet या HashMap के तत्व वापस आते हैं जब आप उन्हें पुन: सक्रिय करते हैं ... यदि तत्व वर्ग hashcode() ओवरराइड नहीं करता है।

यादृच्छिक संख्या जनरेटर निर्धारक हो सकते हैं या नहीं भी हो सकते हैं। अगर वे छद्म-यादृच्छिक हैं और उन्हें निश्चित बीज के साथ शुरू किया जाता है, तो प्रत्येक द्वारा उत्पादित संख्याओं का क्रम निर्धारक होगा।

फ़्लोटिंग पॉइंट अंकगणित निर्धारित होना चाहिए। अंकगणितीय अभिव्यक्ति में इनपुट के किसी भी (निश्चित) सेट के लिए, परिणाम हमेशा एक जैसा होना चाहिए। (मुझे यकीन है कि चल बिन्दु गणित के नियतिवाद JLS द्वारा गारंटीकृत है नहीं कर रहा हूँ, लेकिन यह शक्तिशाली अजीब हो सकता है अगर यह व्यवहार में हुआ था। के रूप में में ... आप टूट हार्डवेयर पर चल रहे हैं।)


FOLLOWUP ... strictfp और गैर-निर्धारणा पर।

JLS 15.4 के अनुसार:

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

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

इसलिए गैर-एफपी-सख्त अभिव्यक्ति मूल्यांकन सिद्धांत में गैर-निर्धारक हो सकता है, मुझे लगता है कि हमें इसे छूट देना चाहिए ... जब तक स्पष्ट सबूत न हो कि यह अभ्यास में होता है।

(ध्यान दें कि मैं वास्तविक गैर नियतिवाद, नहीं मंच मतभेदों के बारे में बात कर रहा हूँ।)

+1

फ्लोटिंग पॉइंट अंकगणित का निर्धारण 'सख्त एफपी' के प्रयोग किए बिना गारंटी नहीं है - लेकिन यह केवल प्लेटफॉर्म पर होना चाहिए। (+1) –

+0

'strctfp' के बिना, कार्यान्वयन कभी-कभी उच्च परिशुद्धता का उपयोग करने के लिए स्वतंत्र होता है और कभी-कभी नहीं। –

+0

@ पॉलबेलोरा - हाँ। प्लेटफार्मों में भिन्नता गैर-निर्धारणा के समान नहीं है। यदि आपके पास सही गैर-निर्धारणवाद था, तो आपका एफपी हार्डवेयर त्रुटिपूर्ण है ... अगर टूटा नहीं है। –

10

मैं सेट throu पुनरावृत्ति कर रहा हूँ, और मुझे पता है कि आदेश में एक सेट दोहराया है definied नहीं है। लेकिन मुझे कोई कारण नहीं दिख रहा है कि एक ही क्रम में एक सेट में भरने वाला सेट कई रनों में अलग-अलग व्यवहार करना चाहिए। क्या यह?

यह कर सकता है। कार्यान्वयन का उपयोग करने के लिए स्वतंत्र है, उदाहरण के लिए, अंतर्निहित हैश तालिका में कुंजी के रूप में स्मृति में ऑब्जेक्ट का स्थान। जब कचरा संग्रह चलता है तो यह अलग-अलग हो सकता है।

+0

@ माइकलबुल्ला - आप किस जेवीएम का उपयोग कर रहे हैं? – tjameson

+0

@tjameson: मैं किसी विशेष JVM का उपयोग नहीं कर रहा हूं। यह प्रश्न इस बारे में है कि * क्या हो सकता है, न कि क्या होता है। –

+0

ऐसा लगता है कि "ऐसा होता है" प्रश्न, और मैं उम्मीद कर रहा था कि यदि ओपी हमें बताता है कि वह किस जेवीएम का उपयोग करता है, तो हम कार्यान्वयन नोट देख सकते हैं और देख सकते हैं कि यह संभावित रूप से कार्यान्वयन के कारण होता है या नहीं। – tjameson

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