कैसे "जबकि (मैं == i)?" एक थ्रेडेड एप्लिकेशन में एक गैर-अनंत लूप हो सकता है?


141

मुझे सिर्फ एक सवाल मिला जिसका मैं जवाब नहीं दे सकता।

मान लीजिए कि आपके पास जावा में यह लूप परिभाषा है:

while (i == i) ;

यदि लूप अनंत लूप नहीं है तो प्रोग्राम किस प्रकार का है iऔर उसका क्या मूल्य है iऔर प्रोग्राम केवल एक थ्रेड का उपयोग कर रहा है ?


7
भगवान के लिए ओह, लोगों को टिप्पणी करने के लिए सम्मान होगा कि वे क्यों नीचा दिखाते हैं? यह एक पहेली के रूप में चिह्नित है, क्या समस्या है ???
user54579

10
मुझे लगता है कि कुछ लोग किसी भी चीज के लिए नीचा दिखाना बंद नहीं कर सकते।
फेरनबी

1
बाह, इस कारण के लिए खेद है: / मैं वास्तव में सिर्फ जवाब चाहता था, और मैं इसे अपने लिए हल नहीं कर सका।
Zizzencs

1
@nickolai, कि एसओ की प्रकृति - डाउन-बाय-डाउन डाउनिंग दुर्भाग्य से एक वास्तविकता है और टिप्पणी की आवश्यकता के विचार पर चर्चा और अस्वीकार कर दिया गया है। लेकिन ऐसा लग रहा है कि "समुदाय" आखिर इस सवाल के पक्ष में है।
पैक्सडिब्लो

1
इस प्रकार के प्रश्नों में से एक ट्रिक यह है कि लोग कुछ निश्चित चर नामों के प्रकार को मान लेते हैं यानी मैं एक int, d एक डबल, s एक स्ट्रिंग या एक छोटा, ch एक चार है, l एक लंबा है, b के लिए है बाइट या बूलियन। आपको खुद से पूछना होगा कि किस प्रकार का सुझाव दिया गया है और यह क्या हो सकता है।
पीटर लॉरी

जवाबों:


125
double i = Double.NaN;

Double.equals () के लिए API उत्तर को बाहर निकालता है: "Double.NaN == Double.NaN का मूल्य गलत है"। यह " फ़्लोटिंग-पॉइंट प्रकार, प्रारूप और मान " के तहत जावा भाषा विशिष्टता में विस्तृत है :

NaN, अव्यवस्थित है तो संख्यात्मक तुलना ऑपरेटरों <, <=, >, और >= वापसी falseकरता है, तो एक या दोनों ऑपरेंड हैं NaN। समानता ऑपरेटर ==रिटर्न falseअगर ऑपरेंड है NaN, और असमानता ऑपरेटर !=रिटर्न trueया तो ऑपरेंड है NaNविशेष रूप से, x!=xहै trueयदि और केवल यदि xहैNaN , और (x<y) == !(x>=y)हो जाएगा falseअगर xया yहै NaN


1
ओह, तो आप "नंबर नहीं" कर सकते हैं!
फिलिप एकबर्ग

12
इसकी गणितीय रूप से ठोस, एक अवास्तविक संख्या एक दूसरे के बराबर क्यों होनी चाहिए? 5/0! = Sqrt (-4)
गॉर्डन गुस्ताफसन

2
@CrazyJugglerDrummer: हो सकता है, लेकिन इसी तरह x == xहमेशा सच होना चाहिए। कुछ भी क्यों नहीं खुद के बराबर होना चाहिए?
बार्ट वैन ह्युकेलम

1
बार्ट: क्योंकि वास्तव में, अज्ञात हमेशा अज्ञात के बराबर नहीं होता है। कभी-कभी यह उपयोगी होता है, इसीलिए डेटाबेस में NULL होता है ...
Konerak

2
@inovaovao: नहीं, एक DB में, null=nullअशक्त है। NULL IS NULLहै 1.
Konerak

29

का मान iतब अमान्य है। "नंबर नहीं"।

कुछ googling के बाद, मुझे पता चला कि आप जावा में NaN (संख्या नहीं) कर सकते हैं! तो, एक फ्लोट पॉइंटिंग नंबर डेटा प्रकार है और मान NaN है। यहाँ देखें


12
हाँ, यह बात है। मैं का मूल्य जॉन स्कीट है।
एंड्रयू रोलिंग

मैं आम तौर पर ऐसे लोगों से नफरत करता हूं जो बिना किसी कारण के नीचा दिखाते हैं ... मैं "नॉट ए नम्बर" कहने वाला पहला व्यक्ति था, लेकिन यह नहीं लगता था कि जावा इसे संभाल सकता है, क्योंकि यह किसी और चीज़ को नहीं संभालता है।
फिलिप एकबर्ग



8

मुझे यकीन नहीं है, लेकिन मेरा मानना ​​है कि (i ==) मल्टीथ्रेडेड प्रक्रिया में परमाणु संचालन नहीं है, इसलिए अगर मैं इसे लूप निष्पादित करने वाले थ्रेड पर स्टैक करने के मूल्य के धक्का के बीच अन्य धागे द्वारा बदल दिया जाएगा, तो वह स्थिति हो सकती है झूठा होना।


8

चूंकि अन्य लोगों ने कहा कि यह NaN है, इसलिए मुझे (JDK 6) के कार्यान्वयन Double.isNaN, और निहारना के बारे में उत्सुक होना पड़ा :

/**
 * Returns <code>true</code> if the specified number is a
 * Not-a-Number (NaN) value, <code>false</code> otherwise.
 *
 * @param   v   the value to be tested.
 * @return  <code>true</code> if the value of the argument is NaN;
 *          <code>false</code> otherwise.
 */
static public boolean isNaN(double v) {
    return (v != v);
}

2

नेन को अपवाद के बराबर समझें लेकिन गणना के भीतर एक जादू मूल्य का उपयोग करता है। क्योंकि एक गणना विफल हो गई - जैसे कि एक ऋणात्मक का वर्गमूल, शून्य आदि से विभाजित - यह उन्हें किसी और चीज के खिलाफ तुलना करने में कोई मतलब नहीं है। सब के बाद अगर शून्य से विभाजित किया जाता है, तो क्या यह नैनो -2 के वर्गमूल या -3 के वर्गमूल के बराबर है?

नान एक गणना की अनुमति देता है जिसमें एक कदम शामिल होता है जो अतिरिक्त अपवादों को पेश किए बिना पूरा करने के लिए एक अमान्य उत्तर देता है। इस बात की पुष्टि करने के लिए कि मूल्य नॉन नॅन्डेनेस के लिए बस टेस्ट है (यह शब्द है अगर मैं इसे बैग नहीं करता हूं) फ्लोट.इसन () ओ समकक्ष के माध्यम से।


3
इसे अपवाद के रूप में सोचना आसान होगा अगर मुझे वास्तव में पता था कि एक अपवाद के रूप में :-) था।
paxdiablo

2

मैं जोड़ूंगा

float i = Float.NaN;

साथ ही साथ

double i = Double.NaN;

इस तरह के प्रश्नों में एक आम ट्रिक यह है कि इस धारणा में कि आप एक इंट हैं। अन्य आम धारणाएं हो सकती हैं कि एक स्ट्रिंग है, एक्स, वाई एक डबल है, च एक चार है, बी एक बाइट है आदि। यदि आप इस तरह से एक प्रश्न देखते हैं तो आप शर्त लगा सकते हैं कि 'मैं' इसका अपेक्षित प्रकार नहीं है।

एक समान प्रश्न है; यह कभी नहीं झुकता है, 'x' क्या है

while(x == x && x != x + 0) { }

एक और सवाल जो मुझे काफी पसंद है; यह लूप एक अनंत लूप है, x के संभावित मान क्या हैं। (: मैं उनमें से बारह गिनता हूँ :)

while(x != 0 && x == -x) { }

0

मुझे पता है कि यह एक जावा प्रश्न है, लेकिन अन्य भाषाओं के लिए प्रश्न पर विचार करना पेचीदा है।

C में, एक सरल प्रकार जैसे कि 'int' ब्रह्मांड को ठंडा होने से पहले समाप्त कर सकता है 'बर्ताव' को बर्ताव करता है अगर 'i' को एक अस्थिर के रूप में घोषित किया गया था (इसलिए संकलक को प्रत्येक पुनरावृत्ति के लिए 'i' के दो पाठ करने के लिए मजबूर किया जाएगा) और अगर 'मैं' वास्तव में स्मृति में था तो कुछ और इसे प्रभावित कर सकता था। तब लूप तब समाप्त होगा जब 'i' एक एकल पुनरावृत्ति के दो रीड्स के बीच बदल जाएगा। ( जोड़ा गया - एक संभावित स्थान - एक माइक्रो-कंप्यूटर में, जहां 'i' वास्तव में I / O पोर्ट के पते पर स्थित होता है, शायद एक स्थिति सेंसर से जुड़ा होता है। यह अधिक प्रशंसनीय होगा यदि 'i' एक पॉइंटर वैरिएबल है ( अस्थिर स्मृति के लिए एक संकेतक) और कथन ' while (*i == *i);' था ।)

जैसा कि अन्य जवाबों के अनुसार, C ++ में, '==' ऑपरेटर को उपयोगकर्ता द्वारा आपूर्ति की जा सकती है यदि मैं उपयोगकर्ता द्वारा परिभाषित वर्ग का हूं, तो कुछ भी संभव हो सकता है।

बजाय SQL-आधारित भाषा में NaN की तरह, लूप अनंत नहीं होगा यदि i का मान NULL था; हालाँकि, कोई भी गैर-पूर्ण मान लूप को अनंत बना देगा। यह जावा की तरह है, जहां कोई भी संख्या (NaN के विपरीत) लूप को अनंत बनाती है।

मैं निर्माण का कोई व्यावहारिक उपयोग नहीं देखता, लेकिन यह एक दिलचस्प सामान्य प्रश्न है।


0

मैं इस समाधान को नहीं देखकर हैरान था:

while (sin(x) == sin(x)) //probably won't eval to true

एक टिप्पणी के जवाब में, इसे चलाने का प्रयास करें:

double x = 10.5f;
assert (x == asin(sin(x)));

x को सिद्धांत में हमेशा आर्किसिन (पाप (x)) के बराबर होना चाहिए, लेकिन व्यवहार में यह नहीं है।


3
क्यों नहीं? आप ठीक उसी डेटा पर एक ही गणना कर रहे हैं, दोनों परिणामों में बिल्कुल समान त्रुटि होगी।
लोरेन Pechtel

मुझे ठीक से याद नहीं है कि मैं इसे कहां पढ़ता हूं, लेकिन आपकी मशीन / कार्यान्वयन के आधार पर, एक फ़ंक्शन कॉल पर पाप (x) एक अलग कॉल के पाप (x) की बराबरी करने का एक छोटा मौका है। इसे फ्लोटिंग पॉइंट डिजिट्स की सटीकता के साथ करना होता है (ट्रिग फ़ंक्शन के बारे में कुछ विशेष है जो उन्हें दो बार समान मूल्य वापस नहीं करता है)।
जॉकी

मेरा अपडेट देखें आर्किन एक्स के पाप को "अनडोज़" करता है, इसलिए उन्हें बराबर होना चाहिए, लेकिन वे नहीं हैं।
जॉकी

यह वही बात नहीं है। जैसे लोरेन ने कहा, आप ठीक उसी ऑपरेशन को अंजाम दे रहे हैं x, जिसमें ठीक उसी अशुद्धि के साथ सटीक परिणाम प्राप्त होना चाहिए। आर्किन फ्लोटिंग पॉइंट नंबरों के साथ एक पाप के परिणाम को उलट नहीं सकता है क्योंकि पास किया गया मान asin()बिल्कुल सटीक नहीं है। इसलिए, asin()गलत होने का परिणाम गलत होगा x == asin(sin(x))। इसके अलावा, आर्किसिन जरूरी नहीं कि एक पाप ऑपरेशन को "पूर्ववत करें" - पाप फ़ंक्शन एक्स के कई मूल्यों के लिए एक ही परिणाम दे सकता है, यही कारण है कि asin()केवल -π / 2 और π / 2 के बीच संख्या देता है।
hbw

2
दूसरे शब्दों में, आर्क्सिन हमेशा पाप कार्य को "पूर्ववत" नहीं कर सकता है क्योंकि आर्क्सिन के लिए यह जानना असंभव है कि मूल कोण क्या था। उदाहरण के लिए, π / 2 और 5 2/2 दोनों के पाप 1. देते हैं। लेकिन आर्क्सिन (1) क्या है? यह स्पष्ट रूप से दोनों को वापस नहीं दे सकता है, है ना? इसलिए, आर्क्सिन का परिणाम 2ians रेडियन की सीमा तक सीमित होना चाहिए, जिसका अर्थ है कि यह वास्तव में पाप फ़ंक्शन के परिणाम को पूर्ववत नहीं कर सकता है जब तक कि मूल कोण 0 और 2π के बीच या C के मामले में नहीं है, -π / 2 π / 2। (वास्तव में, आर्क्सिन (पाप (5π / 2)) = 2/2।) वैसे भी, यह वास्तव में एक लंबा स्पष्टीकरण था, लेकिन मुझे आशा है कि किसी भी गलतफहमी को दूर करने में मदद करता है।
hbw

0

अनंत लूप नहीं, एक धागा :)

import static B.*;
public class A {
    public static void main(String[] args) {
        System.out.println("Still Running");
        while (i == i) ;
    }
}


public class B {

    public static int i;
    static {
        System.exit(0);
    }
}

-1

i == iपरमाणु नहीं है। इस तरह के कार्यक्रम द्वारा साबित:

static volatile boolean i = true;
public static void main(String[] args) throws InterruptedException
{
    new Thread() {
        @Override
        public void run() {
            while (true) {
                i = !i;
            }
        }
    }.start();

    while (i == i) ;
    System.out.println("Not atomic! i: " + i);
}

अद्यतन यहां एक और नहीं-अनंत लूप का उदाहरण है (कोई नया सूत्र नहीं बनाया गया है)।

public class NoNewThreads {
    public static void main(String[] args) {
        new NoNewThreads();
        System.gc();
        int i = 500;
        System.out.println("Still Running");
        while (i == i) ;
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        Thread.sleep(1000);
        System.exit(0);
    }
}

@Charles Goodwin आप इस तथ्य से क्या कहते हैं कि एक धागा का उपयोग करके जावा प्रोग्राम लिखने की कोई संभावना नहीं है :), इसलिए अन्य सभी समाधान कम से कम दो थ्रेड्स का उपयोग करते हैं (बिल्कुल 'अपडेट' सेक्शन में मेरे दूसरे प्रोग्राम के समान)।
एंड्री

यह लूप ब्रेकिंग नहीं है। while (i == i);अभ्यस्त होने के बाद कोई भी कोड ।
अकलु

अंतिम रूप एक और धागे का उपयोग करता है, लेकिन यह इंगित करने के लिए एक अच्छी बात है। यही कारण है कि मूल प्रश्न ने कहा "और कार्यक्रम केवल एक धागे का उपयोग करता है" .. स्पष्ट रूप से यह कहते हुए कि यह स्पष्ट उत्तर है और वे आपके आगे देखने की इच्छा रखते हैं।
बिल के
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.