एक यादृच्छिक संख्या पैदा करने के लिए एल्गोरिथ्म

वोट
7

मैं एक यादृच्छिक संख्या पैदा करते हैं और एक विशेष user_id के लिए एक डेटाबेस में एक मेज पर इसे जारी करने के लिए देख रहा हूँ। पकड़, एक ही नंबर दो बार इस्तेमाल किया जा नहीं कर सकता है। ऐसा करने के एक लाख तरीके है, लेकिन मैं आशा करती हूं कि किसी एल्गोरिदम पर बहुत उत्सुक है कि निम्नलिखित मानदंडों में एक सुरुचिपूर्ण समाधान में समस्या के हल के लिए एक चतुर तरीका है पूरा किया जाता है:

1) डेटाबेस के लिए प्रश्नों की कम से कम मात्रा बना रहे हैं। 2) स्मृति में एक डेटा संरचना के माध्यम से रेंगने कम से कम मात्रा किया जाता है।

अनिवार्य रूप से विचार निम्नलिखित करना है

1) 9999999 0 से एक यादृच्छिक संख्या बनाएं
2) डेटाबेस चेक संख्या मौजूद है, तो देखने के लिए
या
2) सभी नंबरों के लिए डेटाबेस क्वेरी
3) देखने के लिए कि प्राप्त परिणाम मैचों जो कुछ db से आया
4) यदि यह मेल खाता है, बार-बार चरण 1, अगर नहीं, समस्या हल हो रहा है।

धन्यवाद।

26/11/2008 को 02:44
का स्रोत उपयोगकर्ता
अन्य भाषाओं में...                            


17 जवाब

वोट
1

मुझे लगता है कि आप पाएंगे कि आप वास्तव में यह करने के लिए नहीं करना चाहती। डेटाबेस वृद्धि में संख्या के रूप में, आप "यह सुनिश्चित करने के लिए इस नंबर नहीं लिया जाता है" पाश में बहुत अधिक समय खर्च कर सकते हैं।

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

26/11/2008 को 02:51
का स्रोत उपयोगकर्ता

वोट
1

मेरा अनुभव बस PHP में RNG उपयोग कर रहा था। मैंने पाया है कि संख्या की एक निश्चित आकार का उपयोग (मैं एक पूर्णांक उपयोग कर रहा हूँ, इसलिए मैं 4 जी की एक अधिकतम है)। मैं कुछ परीक्षण भाग गया और पाया गया कि औसतन, 500,000 पुनरावृत्तियों में, मैं 120 एकल डुप्लिकेट मिला है। मैंने कभी नहीं पाश समय की एक गुच्छा चलाने के बाद एक तीन प्रतियों मिला है। मेरे "समाधान" फिर बस डालने और देखें कि क्या यह विफल रहता है, तो एक नया आईडी पैदा करते हैं और फिर से जाना था।

मेरी सलाह भी ऐसा ही और देखें कि आपके टक्कर दर है और सी और देखें कि क्या वह अपने मामले के लिए स्वीकार्य है के लिए है।

यह इष्टतम नहीं है, तो मैं भी देख रहा हूँ अगर किसी को भी सुझाव है :)

संपादित करें: मैं एक 5 अंक आईडी ([एक-zA-Z0-9] {5,5}), अब आईडी (अधिक संयोजन, कुछ टकराव) तक ही सीमित था। ईमेल की एक md5 लगभग संघर्ष कभी नहीं होगा, उदाहरण के लिए।

26/11/2008 को 02:51
का स्रोत उपयोगकर्ता

वोट
17

कोई अपने एल्गोरिथ्म स्केलेबल नहीं है। क्या मैंने पहले किया है क्रमानुसार नंबर जारी (+1 हर बार) और फिर बिट्स इस प्रकार मुझे एक मालूम होता है यादृच्छिक संख्या दे रही गड़बड़ी के लिए एक XOR आपरेशन के माध्यम से उन्हें पारित करने के लिए है। बेशक वे वास्तव में यादृच्छिक नहीं हैं, लेकिन वे उन आंखों को तो देखो।


[संपादित करें] अतिरिक्त जानकारी

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

लेकिन अगर आप गति से अधिक, एन्क्रिप्शन के अन्य रूपों का उपयोग करता है, तो आप और भी अधिक यादृच्छिक देख संख्या पसंद करते हैं चाहते हैं कर सकते हैं, (कहते हैं कि तुम एक समय में कई आईडी उत्पन्न करने के लिए की जरूरत नहीं है)। अब एक एन्क्रिप्शन एल्गोरिथ्म को चुनने में महत्वपूर्ण बिंदु "गारंटी नहीं है कि संख्या टकराने कभी नहीं होगा" है। और एक तरह से साबित करने के लिए करता है, तो एक एन्क्रिप्शन एल्गोरिथ्म इस गारंटी को पूरा कर सकते जाँच करने के लिए करता है, तो दोनों मूल संख्या और एन्क्रिप्शन का परिणाम बिट्स की एक ही नंबर है, और कलन विधि प्रतिवर्ती (द्विभाजन) है।

[के लिए धन्यवाद एडम लिस और CesarB समाधान पर exapanding के लिए]

26/11/2008 को 02:51
का स्रोत उपयोगकर्ता

वोट
1

समस्या यह है कि आप यादृच्छिक संख्या पैदा कर रहे हैं, तो बहुत संभव है डुप्लिकेट infinatly उत्पादन होता है।

तथापि:

<?php
//Lets assume we already have a connection to the db
$sql = "SELECT randField FROM tableName";
$result = mysql_query($sql);
$array = array();
while($row = mysql_fetch_assoc($result))
 {
   $array[] = $row['randField'];
 }
while(True)
 {
   $rand = rand(0, 999999);
   if(!in_array($rand))
     {
       //This number is not in the db so use it!
       break;
     }
 }
?>

हालांकि यह है कि तुम क्या यह भी चाहते हो जाएगा, यह इस रूप में एक बुरा विचार लंबे समय के लिए स्केल नहीं करेगा, eventualy अपने सरणी बड़ी करने के लिए मिल जाएगा और यह उत्पन्न करने के लिए एक यादृच्छिक है कि आपके DB में पहले से ही नहीं है, लेकिन बहुत लंबा समय लगेगा है ।

26/11/2008 को 02:55
का स्रोत उपयोगकर्ता

वोट
2

मान लिया जाये कि:

  • अनियमितता की सुरक्षा के लिए विशिष्टता के लिए की जरूरत है, नहीं
  • आपका user_id 32 बिट है
  • 9999999 की अपनी सीमा सिर्फ एक उदाहरण था

तुम कुछ एक 64 बिट पूर्णांक के रूप में यादृच्छिक संख्या होने के रूप में सरल, ऊपरी 32 (पंक्ति सम्मिलित करने पर) टाइमस्टैम्प युक्त बिट और कम 32 बिट user_id के साथ कर सकता। यही कारण है कि प्रदान की आप कितनी बार आप एक ही उपयोगकर्ता के लिए नई पंक्तियाँ जोड़ने के आधार पर अपने टाइमस्टैम्प पर एक उपयुक्त संकल्प का उपयोग, यहां तक ​​कि एक ही उपयोगकर्ता के साथ अनेक पंक्तियों के लिए अद्वितीय होगा। यादृच्छिक स्तंभ पर एक अद्वितीय बाधा के साथ गठबंधन करने और अपने तर्क में किसी भी तरह के त्रुटि को पकड़ और फिर बस का प्रयास करें।

26/11/2008 को 03:00
का स्रोत उपयोगकर्ता

वोट
1

यह nonrepetition की एक लंबी अवधि के साथ एक कूट-यादृच्छिक संख्या जनरेटर डिजाइन करने के लिए आसान है; जैसे यह एक है, जो एक ही बात है कि आप इसके लिए चाहते हैं के लिए इस्तेमाल किया जा रहा है।

Btw, क्यों नहीं बस userid का क्रमिक रूप से जारी?

26/11/2008 को 03:02
का स्रोत उपयोगकर्ता

वोट
0

पीएचपी पहले से ही इस के लिए एक समारोह है, uniqid । यह एक मानक UUID जो महान है आपको कहीं और से डेटा का उपयोग करने के लिए है, तो उत्पन्न करता है। पहिया बदलने मत करो।

26/11/2008 को 03:06
का स्रोत उपयोगकर्ता

वोट
6

एक से शीर्ष पर समाधान करना चाहते हैं?

मैं अनियमितता एन्क्रिप्शन गुणवत्ता, लेकिन सिर्फ एक उपयोगकर्ता की लंबी उम्र अनुमान लगा, user_id से हतोत्साहित करने के लिए पर्याप्त होना करने के लिए इरादा नहीं है मान लेते हैं।

विकास के दौरान, स्ट्रिंग रूप में सभी 10 लाख नंबरों की सूची उत्पन्न करते हैं।

वैकल्पिक रूप से, मध्यम करने के लिए एक निरंतर स्ट्रिंग को जैसे चाहें, कुछ सरल परिवर्तन प्रदर्शन करते हैं। (यह सिर्फ मामले में परिणाम भी उम्मीद के मुताबिक है।)

उन्हें एक उपकरण है जो उत्पन्न करता है में पारित बिल्कुल सही हैश कार्यों जैसे, gperf

जिसके परिणामस्वरूप कोड जल्दी से एक अनूठा हैश मान होता है किसी भी अन्य हैश मान के साथ संघर्ष करने के लिए नहीं की गारंटी है में कार्यावधि में उपयोगकर्ता की आईडी एन्कोड करने के लिए इस्तेमाल किया जा सकता।

26/11/2008 को 03:16
का स्रोत उपयोगकर्ता

वोट
17

आप क्यों नहीं बस एक GUID का उपयोग नहीं करते? अधिकांश भाषाओं निर्मित एक तरीका यह है होना चाहिए। यह (बहुत ही उचित सीमा के साथ) अद्वितीय होने की गारंटी है।

26/11/2008 को 03:19
का स्रोत उपयोगकर्ता

वोट
1

मैं Oddthinking के विचार, लेकिन इसके बजाय दुनिया में, आप बस सकता है सबसे मजबूत हैश फंक्शन को चुनने का पसंद:

  • MD5 की संख्या के पहले 10 लाखों की (तार के रूप में व्यक्त, + कुछ नमक) उत्पन्न
  • डुप्लिकेट के लिए जाँच करें ऑफ़लाइन यानी उत्पादन में जाने से पहले, (मुझे लगता है कि वहाँ किसी भी नहीं होगा)
  • एक सरणी में डुप्लिकेट स्टोर कहीं
  • आपका आवेदन शुरू होता है, सरणी लोड
  • आप एक आईडी डालने के लिए चाहते हैं, तो, अगले संख्या चुन अपने MD5 गणना, अगर यह सरणी में है की जाँच, और यह डेटाबेस में आईडी के रूप में उपयोग नहीं किया जाता है। अन्यथा, अगले संख्या चुन

MD5 की तेजी से कर रहे हैं, और यह जांच एक स्ट्रिंग एक सरणी के अंतर्गत आता है अगर आप एक का चयन नहीं आने देगा।

26/11/2008 को 03:41
का स्रोत उपयोगकर्ता

वोट
3

mysql का चयन करें कास्ट में बयान का प्रयास करें (RAND () * 1000000 INT के रूप में)

26/11/2008 को 08:51
का स्रोत उपयोगकर्ता

वोट
1

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

26/11/2008 को 11:13
का स्रोत उपयोगकर्ता

वोट
0

मैं शायद अपनी बात है, लेकिन क्या auto_increments के बारे में समझ नहीं आया?

27/11/2008 को 19:11
का स्रोत उपयोगकर्ता

वोट
1

क्या तुम सच में "यादृच्छिक" संख्या प्रपत्र 0 से 9 तक 999 999 पाने के लिए चाहते हैं, तो समाधान "यादृच्छिकीकरण" एक बार ऐसा करने के लिए, और फिर अपने डिस्क के लिए परिणाम की दुकान है।

यह परिणाम आप चाहते हैं पाने के लिए मुश्किल नहीं है, लेकिन मैं और अधिक "संख्या के साथ एक लंबी सूची बनाने" की तरह इसके बारे में लगता है, "एक यादृच्छिक संख्या प्राप्त" की तुलना में।

$array = range(0, 9999999);
$numbers = shuffle($array);

तुम भी $ संख्या (एक डेटाबेस में संग्रहीत) में वर्तमान स्थिति के लिए सूचक की जरूरत है; 0 के साथ शुरू और यह हर बार जब आप एक नया नंबर की जरूरत को बढ़ा देते। (या आप array_shift (इस्तेमाल कर सकते हैं) या array_pop (), यदि आप संकेत का उपयोग करना चाहते नहीं है।)

27/11/2008 को 23:41
का स्रोत उपयोगकर्ता

वोट
1

एक उचित PRNG (छद्म यादृच्छिक संख्या जनरेटर) एल्गोरिथ्म एक समय चक्र जिसके दौरान यह एक ही राज्य में कभी नहीं होगा होगा। आप संख्या यह से लिया गया में PRNG के पूरे राज्य का पर्दाफाश, तो आप एक संख्या जनरेटर की अवधि के लिए अद्वितीय की गारंटी मिल जाएगा।

एक साधारण PRNG कि यह करता है 'कहा जाता है रैखिक congruential ' PRNG जो एक सूत्र iterates:

X(i) = AX(i-1)|M

कारकों में से सही जोड़ी का उपयोग करके आप एक 32 बिट संचायक के साथ एक सरल PRNG से 2 ^ 30 (लगभग 1 अरब) की अवधि के प्राप्त कर सकते हैं। ध्यान दें कि आप एक 64 बिट लंबे गणना के मध्यवर्ती 'कुल्हाड़ी' भाग धारण करने के लिए अस्थायी चर की आवश्यकता होगी। अधिकांश नहीं तो सब सी compilers इस डेटा प्रकार का समर्थन करेंगे। तुम भी सबसे एसक्यूएल बोलियों पर एक संख्यात्मक डेटा प्रकार के साथ यह करने के लिए सक्षम होना चाहिए।

ए और एम के अधिकार के मूल्यों के साथ हम अच्छा सांख्यिकीय और ज्यामितीय गुणों के साथ एक यादृच्छिक संख्या जनरेटर मिल सकती है। इस फिशमैन और मूर द्वारा लिखित के बारे में एक प्रसिद्ध कागज है।

के लिए एम = 2 ^ 31 - 1 हम एक अच्छा लंबी अवधि (2 ^ 30 IIRC) के साथ एक PRNG प्राप्त करने के लिए एक नीचे के मूल्यों का उपयोग कर सकते हैं।

एक के अच्छे संस्कार:

742,938,285  
950,706,376  
1,226,874,159  
62,089,911  
1,343,714,438   

ध्यान दें कि जनरेटर के इस प्रकार (परिभाषा के द्वारा) है क्रिप्टोग्राफी द्वारा सुरक्षित नहीं। आप इसे से उत्पन्न पिछले नंबर पता है आप भविष्यवाणी कर सकते हैं क्या यह आगे क्या होगा। दुर्भाग्य से मुझे विश्वास है कि आप क्रिप्टोग्राफिक सुरक्षा और गारंटी गैर repeatability एक ही समय में नहीं मिल सकता है। एक PRNG क्रिप्टोग्राफी द्वारा सुरक्षित होने के लिए (जैसे ब्लम ब्लम Shub ) यह पर्याप्त राज्य एक जनरेट की गई संख्या में खुलासा नहीं कर सकते हैं क्रम में अगला नंबर की भविष्यवाणी की जा करने के लिए अनुमति देने के लिए। इसलिए आंतरिक स्थिति जनरेट की गई संख्या से अधिक व्यापक और अवधि संभावित मान है कि उत्पन्न किया जा सकता की संख्या से अधिक समय हो जाएगा (क्रम अच्छा सुरक्षा पाने के लिए) है। इसका मतलब है कि उजागर संख्या अवधि के भीतर अद्वितीय नहीं होगा।

इसी तरह के कारणों के लिए एक ही तरह के रूप में लंबी अवधि जनरेटर का सच है Mersenne ट्विस्टर।

27/11/2008 को 23:59
का स्रोत उपयोगकर्ता

वोट
1

वहाँ कुछ तरीके यह एक तरह से के बारे में जाने के लिए नंबर 0000000 9999999 के माध्यम से के साथ एक सरणी का निर्माण और उसके बाद इस सरणी में इन नंबरों के एक यादृच्छिक ले लेने और उच्चतम मूल्य अधिकतम तब तक अधिकतम कम करने के साथ उठाया संख्या मूल्यों स्वैप करने के लिए होगा 1 और नए अधिकतम करने के लिए इस सरणी का एक और यादृच्छिक सदस्य लेने

हर बार एक के बाद मैक्स को कम करने

उदाहरण (मूल में) के लिए: (करने के लिए सही टिप्पणियों जो वास्तविक कार्यक्रम में हटा दिया जाना चाहिए रहे हैं) Rndfunc प्रयोग कर रहे हैं जो कुछ यादृच्छिक संख्या जनरेटर फ़ंक्शन की कॉल है

dim array(0 to 9999999) as integer
for x% = 1 to 9999999
array(x%)=x%
next x%
maxPlus = 10000000
max =9999999
pickedrandom =int(Rndfunc*maxPlus)  picks a random indext of the array based on    
                                   how many numbers are left
maxplus = maxplus-1
swap array(pickedrandom) , array(max) swap this array value to the current end of the
                                     array 
max = max -1                   decrement the pointer of the max array value so it 
                              points to the next lowest place..

उसके बाद प्रत्येक नंबर पर आप लेने के लिए इच्छा के लिए ऐसा करना जारी रखें, लेकिन आप बहुत बड़ा सरणियों का उपयोग करने का विकल्प होता है करने की आवश्यकता होगी

अन्य विधि इस प्रकार होगा: एक नंबर पैदा करते हैं और यह एक सरणी है कि गतिशील रूप से तो बढ़ सकता है में स्टोर के बाद कि एक नया नंबर लेने और मूल्य इस मामले में सरणी में पिछले तत्व करने के लिए पहले से आधे रास्ते है कि की तुलना यह पहले नंबर उठाया अगर यह, एक और यादृच्छिक संख्या लेने आकार के अनुसार सरणी सॉर्ट मेल खाता है और अगर वहाँ एक मैच नहीं है तो मौसम पर निर्भर करता है यह अधिक से अधिक या नंबर पर आप यह तुलना के साथ ऊपर या में नीचे जाना तुलना में छोटा होता होगा आधा दूरी की सूची आधा, हर बार है कि यह मेल नहीं खाता और अधिक से अधिक या क्या आप इसे करने के तुलना कर रहे हैं की तुलना में कम है।

हर बार इतने पर जब तक आप कर रहे हैं यह आधा जब तक आप तो आप एक बार की जाँच करें और वहाँ के रूप में कोई मुकाबला नहीं है, और उसके बाद नंबर सूची में जोड़ा जाता है और सूची आरोही क्रम में फेरबदल किया गया है को रोकने के एक के अंतराल के आकार तक पहुँचने, इतने पर और यादृच्छिक संख्या उठा किया ... उम्मीद है कि इस मदद करता है ..

27/01/2012 को 14:05
का स्रोत उपयोगकर्ता

वोट
0

आप यह सुनिश्चित करें कि यादृच्छिक संख्या दोहरा नहीं कर रहे हैं चाहते हैं, आप (के रूप में वर्णित किसी न दोहराई यादृच्छिक संख्या-जनरेटर की जरूरत है यहाँ )।

मूल विचार यह है कि निम्न सूत्र है seed * seed & pकिसी भी इनपुट के लिए न दोहराई यादृच्छिक संख्या का उत्पादन किया जाएगा x such that 2x < pऔर p - x * x % pन दोहराई, लेकिन केवल तभी अच्छी तरह से अन्य सभी यादृच्छिक संख्या का उत्पादन p = 3 mod 4। तो बुनियादी तौर पर आप सभी की जरूरत के लिए एक एकल primnumber के रूप में के करीब है 9999999के रूप में संभव। इस तरह, लेकिन नकारात्मक पक्ष यह है कि या तो बहुत बड़ा आईडी उत्पन्न कर रहे हैं या बहुत कम आईडी उत्पन्न हो जाएगा के साथ प्रयास एक भी पढ़ने के लिए फ़ील्ड को कम किया जा सकता है।

इस एल्गोरिथ्म बहुत अच्छी तरह से दूसरे स्थान पर रखना नहीं करता है, तो मैं या तो XOR या इसके अलावा या कुछ अन्य दृष्टिकोण के बीज और उनके उत्पन्न मूल्य के बीच 1 से 1-संबंध को नष्ट किए बिना सही मूल्य को बदलने के लिए के साथ संयोजित सलाह देते हैं।

04/10/2015 को 22:49
का स्रोत उपयोगकर्ता

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more