2011-06-22 30 views
31

मैं एक सीमा के भीतर एक यादृच्छिक संख्या कैसे उत्पन्न लेकिन कुछ बाहर करते हैं, रखें पैदा करने के बिना और यदि जनरेट की गई संख्या उन है कि मैं बाहर करना चाहते हैं में से एक है की जाँच कर सकते हैं?मैं एक सीमा के भीतर एक यादृच्छिक संख्या कैसे उत्पन्न कर सकता हूं लेकिन कुछ को बाहर कर सकता हूं?

+0

आप एक पूर्णांक या डबल यादृच्छिक संख्या चाहते हैं? – Snicolas

+0

क्या आपके पास अपनी सीमा में इतने सारे बहिष्कार हैं कि यह एक बहिष्कृत संख्या को मारने की संभावना है? –

उत्तर

41

एक उत्थान के बिना संभव समाधान यादृच्छिक हर बार निम्नलिखित कलन विधि का उपयोग करने के लिए है :

public int getRandomWithExclusion(Random rnd, int start, int end, int... exclude) { 
    int random = start + rnd.nextInt(end - start + 1 - exclude.length); 
    for (int ex : exclude) { 
     if (random < ex) { 
      break; 
     } 
     random++; 
    } 
    return random; 
} 

इस विधि को या तो सरणी संदर्भ के साथ बुलाया जा सकता है, उदाहरण के लिए

int[] ex = { 2, 5, 6 }; 
val = getRandomWithExclusion(rnd, 1, 10, ex) 

या सीधे कॉल में नंबर डालने से:

val = getRandomWithExclusion(rnd, 1, 10, 2, 5, 6) 

यह start और end (दोनों सहित) के बीच एक यादृच्छिक संख्या (पूर्णांक) उत्पन्न करता है और आप किसी भी संख्या जो निहित है नहीं देता है सरणी exclude में। अन्य सभी संख्या बराबर संभावना के साथ होती है। ध्यान दें, जो निम्न constrains पकड़ चाहिए: exclude ascendingly क्रमबद्ध हो जाता है और सभी नंबरों को प्रदान की सीमा के भीतर हैं और उन सभी परस्पर भिन्न हैं।

+0

+1 "को यहां छोड़ना चाहता हूं। लेकिन मैं लूप के अंदर 'यादृच्छिक

+0

@ घातक समायोजित कोड। – Howard

+0

@ फाटल, @ हावर्ड, यह एक बेहद चालाक समाधान है। आपने इसके बारे में कहाँ से सीखा या आप इसके साथ कैसे आए? सबसे पहले मुझे यकीन था कि यह काम नहीं करेगा लेकिन इसके माध्यम से कदम उठाने के बाद मुझे पता चला कि यह निश्चित रूप से काम करता है और मैं प्रभावित हूं। रोजमर्रा के कोड के लिए मैं इसे हमारे कोडबेस में नहीं देखना चाहता क्योंकि यह पठनीयता की महंगी कीमत पर गति देता है। – Paul

1

एक नक्शा है कि सीमा के प्रतिबंध के बिना एक यादृच्छिक समारोह के उत्पादन में ले जाता है और सीमा आप प्रतिबंधों के साथ चाहते हैं कि यह नक्शा बनाएँ। जब तक

int i = rand(1, 9); 
if i>=7 
    i++; 
return i; 

के रूप में आप सुनिश्चित करें कि आपके मानचित्रण 1 है कि:

उदाहरण के लिए, अगर मैं 1-10 से एक यादृच्छिक पूर्णांक चाहते हैं, लेकिन कभी नहीं 7 मैं कुछ इस तरह कर सकता है 1, आप बच सकते हैं अपने rand फ़ंक्शन की यादृच्छिकता को तिरछा करना।

+0

दूसरा रास्ता दौर बेहतर होगा: 1 से 8 तक संख्याएं बनाएं और 7 और 8 से 8 और 9 तक मानचित्र बनाएं। इस तरह आप वितरण को बनाए रखते हैं। – keuleJ

+0

@keuleJ: आप 9 से 10 मैपिंग के बारे में भूल गए हैं इसके अलावा, यह केवल एक मामूली उदाहरण के रूप में था। आप जिस भी मानचित्र के साथ आते हैं वह आपके एल्गोरिदम के लिए विशिष्ट होगा। जब तक आपका नक्शा सुसंगत हो (प्रत्येक संभावित इनपुट मैप्स आउटपुट की एक ही संख्या में और प्रत्येक वांछित आउटपुट को संभावित इनपुट की उसी संख्या से मैप किया जाता है) आप वितरण को बनाए रखेंगे। –

+0

@ एक्सएक्स आप सही हैं। लेकिन आपने 7 और 8 से 8 तक मैप किया। इस तरह के एल्गोरिदम में वितरण को गड़बड़ करना आसान है ... – keuleJ

0

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

0

कुछ ऐसा काम करते हैं और दोनों पर लागू होता है हो सकता है int करने के लिए और डबल नंबर की तरह हो सकता है:

public int getRandomNumberWithExclusion(int start, int end) 
{ 
    Random r = new Random(); 
    int result = -1; 

    do 
    { 
     result = start + r.nextInt(end - start); 
    }//do 
    while(!isAllowed(result)); 

    return result; 

}//met 

private boolean isAllowed(int number) 
{ 
    //your test for restricted values here 
}//met 

सादर, स्टीफन

+0

"[...] उत्पन्न होने और जांचने के बिना अगर उत्पन्न संख्या उन लोगों में से एक है जिन्हें मैं" –

3

सबसे अच्छा aproach कि आप संख्याओं randomize करने के लिए अनुसरण कर सकते हैं, कुछ जो नंबर आप पहले और उसके बाद चाहते हैं कि बेतरतीब ढंग से चुना संख्या का चयन चुन रही है, को छोड़कर। उदाहरण के लिए, स्यूडोकोड में के लिए:

List<Number> numbers; 

numbers.add(1); 
numbers.add(2); 
numbers.add(3); 
//You can do a "for" without adding the excluded numbers.. 

//Then, your randomizer could be... 

public Number getRandoNumber() { 
    int index = Random.get(0, numbers.size()); 
    return numbers.get(index); 
} 

अब, आप जांच करने के लिए "जनरेट की गई संख्या" या अनुमति नहीं है अगर है, क्योंकि यह सब पर मौजूद नहीं है की जरूरत नहीं है।

Collections.shuffle(numbers); 

public Number getRandomNotRepeat() { 
    if(numbers.size() == 0) 
     throw new RuntimeException("No more numbers"); 

     Number n = numbers.get(0); 
     numbers.removeFirst(); 

     return n; 
} 

यह सब छद्म कोड, इसे कॉपी करके पेस्ट है:

आप नहीं है तो उन्हें दोहराने के लिए, आप की तरह कुछ कर सकते हैं चाहता हूँ!

15
/** 
* @param start start of range (inclusive) 
* @param end end of range (exclusive) 
* @param excludes numbers to exclude (= numbers you do not want) 
* @return the random number within start-end but not one of excludes 
*/ 
public static int nextIntInRangeButExclude(int start, int end, int... excludes){ 
    int rangeLength = end - start - excludes.length; 
    int randomInt = RANDOM.nextInt(rangeLength) + start; 

    for(int i = 0; i < excludes.length; i++) { 
     if(excludes[i] > randomInt) { 
      return randomInt; 
     } 

     randomInt++; 
    } 

    return randomInt; 
} 

विचार जिसमें यादृच्छिक संख्या कि सीमा है कि बाहर रखा गया है के अंतर्गत संख्याओं के आरंभ और अंत शून्य से गिनती के बीच अंतर करने के लिए उत्पन्न होता है सीमा को कम किया जा सके।

तो आपको एक सीमा लंबाई मिलती है जो संभावित मान्य संख्याओं की गणना के समान है। दूसरे शब्दों में: आपने सीमा से सभी छेद हटा दिए हैं।

यादृच्छिक संख्या उत्पन्न करने के बाद आपको "छेद" को सीमा में वापस रखना होगा। यह जेनरेट किए गए नंबर को बढ़ाकर हासिल किया जा सकता है जब तक कि उत्पन्न संख्या से कम या उसके बराबर संख्या न हो। उत्पन्न संख्या से पहले सीमा में निचले बहिष्कृत संख्याएं "छेद" हैं। और जेनरेट संख्या उस संख्या से पहले हर छेद के लिए दाईं ओर स्थानांतरित हो जाती है।

+0

javadoc टिप्पणियों और सार्थक कोड –

2

मुझे लगता है कि अतिरिक्त सवाल यह है: आप कितनी संख्याएं निकालना चाहते हैं? क्या वे रेंज का प्रतिनिधित्व करते हैं या वे पूरी तरह से यादृच्छिक हैं?

यदि ऐसा है तो आप की अनदेखी करने के लिए, आप कुछ सेट है कि केवल वैध संख्या का प्रतिनिधित्व के भीतर से अपने यादृच्छिक संख्या उत्पन्न कर सकता है चाहता हूँ संख्या की श्रेणी:

rand(1,9); 
rand(15,19); 
rand(22,26); 

इस तरह क्या आप वाकई शामिल का चयन कभी नहीं होगा रहे हैं: < 0,10,11,12,13,14,20,21,> 27

फिर, जब आप अपने 3 नंबर प्राप्त करते हैं, तो आप फिर से यादृच्छिक रूप से उनमें से एक का चयन कर सकते हैं।

यदि बहिष्कृत संख्याएं मुझे डरने की जगह से अधिक जगह पर हैं तो आपको इसे किसी भी प्रकार के बहिष्कृत संख्याओं के संग्रह के खिलाफ हर बार जांचना होगा।

+0

के कारण अच्छा जवाब मुझे अपने पहले के कथन को वापस लेना पड़ा। हालांकि यह एक अच्छा विचार प्रतीत होता है, यह वास्तव में परिणामों को तब तक छोड़ देता है जब तक कि "चयनित" श्रेणियों में से प्रत्येक बराबर आकार के न हों। मान लें कि मैं संख्या 2 से 10 तक किसी सीमा से बहिष्कृत करना चाहता हूं, संख्या 0 और 1 शेष संख्याओं की तुलना में दो बार और अक्सर दिखाई देगी। इसे ठीक करने के लिए, आपको बड़ी श्रेणियों से यादृच्छिक संख्या चुनने का पक्ष लेना होगा, लेकिन मुझे यकीन नहीं है कि इसे कैसे समायोजित किया जाए और यहां तक ​​कि वितरण को बनाए रखा जाए। – Carcigenicate

0

को बाहर संख्या रेंज पैरामीटर में साथ होना चाहिए

private int GiveMeANumber(int range,int... exclude) 
{ 

    Set<Integer> integers=new HashSet<>(); 
    int count=range; 

    for(int i=0;i<count;i++) 
     integers.add(i); 

    integers.removeAll(Arrays.asList(exclude)); 


    int index = new Random().nextInt(range - exclude.length); 

    count=0; 

    for (int value:integers){ 
     if(count==index) 
      return value; 

     count++; 
    } 


    return 0; 
} 
संबंधित मुद्दे

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