2015-11-17 13 views
7

के साथ पोस्टग्रेस्क्ल में अद्वितीय यादृच्छिक संख्याएं उत्पन्न करें मुझे पोस्टग्रेस्क्ल में 13 अंकों की निश्चित लंबाई के साथ अद्वितीय यादृच्छिक संख्याएं उत्पन्न करने की आवश्यकता है। मुझे एक समान thread मिला है जहां "pseudo_encrypt" का उपयोग करके एन्क्रिप्टेड अनुक्रम का उपयोग किया गया था, लेकिन लौटा हुआ नंबर निश्चित लंबाई के साथ नहीं था।निश्चित लंबाई

तो, मैं क्या जरूरत है: 13 अंकों जहां न्यूनतम मूल्य 0000000000001 है की एक निश्चित लंबाई और एक अधिकतम मूल्य के साथ एक एन्क्रिप्टेड यादृच्छिक अनुक्रम मिल 9999999999999.

है यह संभव है? यदि सामने के शून्य से शुरू करना संभव नहीं है, तो मुझे कोई बड़ी समस्या नहीं है (मुझे लगता है), मैं उन्हें डीबी से पढ़ने के दौरान प्रोग्रामेटिक रूप से सेट कर सकता हूं, लेकिन अगर पोस्टग्रेस्क्ल इसे स्वयं कर सकता है तो अच्छा होगा।

- संपादित करें -

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

मैं साथ Postgresql में अद्वितीय यादृच्छिक संख्या (bigint) उत्पन्न करने के लिए की जरूरत है 13 अंकों की एक निश्चित अधिकतम लंबाई। असल में मैं pseudo_encrypt फ़ंक्शन (64 बिट) का उपयोग करने की कोशिश कर रहा हूं, लेकिन वापसी की गई संख्या स्पष्ट रूप से 13 की निश्चित अधिकतम लंबाई के साथ नहीं है, 32 बिट मामले में अधिकतम लंबाई 10 अंक (int) है, और 64 बिट के लिए है 1 9 (बड़ा)।

तो, 13 अंकों की एक निश्चित अधिकतम लंबाई के साथ एक एन्क्रिप्टेड यादृच्छिक अनुक्रम कैसे प्राप्त करें, जहां न्यूनतम मान 1 है और अधिकतम मान 99 99 99 99 99 999 है?

क्या यह परिणाम प्राप्त करने के लिए 64 बिट pseudo_ecrypt फ़ंक्शन को संशोधित करना संभव है? या यदि संभव नहीं है, तो इस आवश्यकता के साथ एक अद्वितीय अनुक्रम प्राप्त करने के अन्य तरीके हैं?

छद्म एन्क्रिप्ट समारोह (64 बिट)

CREATE OR REPLACE FUNCTION pseudo_encrypt(VALUE bigint) returns bigint AS $$ 
DECLARE 
l1 bigint; 
l2 bigint; 
r1 bigint; 
r2 bigint; 
i int:=0; 
BEGIN 
l1:= (VALUE >> 32) & 4294967295::bigint; 
r1:= VALUE & 4294967295; 
WHILE i < 3 LOOP 
    l2 := r1; 
    r2 := l1 # ((((1366.0 * r1 + 150889) % 714025)/714025.0) * 32767*32767)::int; 
    l1 := l2; 
    r1 := r2; 
    i := i + 1; 
END LOOP; 
RETURN ((l1::bigint << 32) + r1); 
END; 
$$ LANGUAGE plpgsql strict immutable; 
+1

आप उस फ़ंक्शन से लौटाए गए मान को निश्चित लंबाई के लिए प्रारूपित कर सकते हैं: 'to_char (pseudo_encrypt (nextval ('seq') :: int), '0000000000000') ' –

+0

और अनुक्रम के बारे में क्या? मुझे इसे कैसे सेट करना है? – MattC

+0

आपके द्वारा लिंक किए गए प्रश्न के समान ही। बस सुनिश्चित करें कि आपके पास अधिकतम मान है जो 13 अंकों से अधिक नहीं है। –

उत्तर

11

N के लिए मौजूदा समारोह ट्वीक < 64 बिट्स को महत्व देता

यह bigint संस्करण बदलाव करने के लिए उत्पादन को कम करने के लिए अपेक्षाकृत आसान है 2^N मान, जहां N भी है, और 64 से भी कम है।

13 दशमलव अंक प्राप्त करने के लिए, अधिकतम N पर विचार करें, जिसके लिए 2^N में 13 अंक हैं। यह एन = 42 है, 2^42=4398046511104 के साथ।

एल्गोरिदम इनपुट मान को दो हिस्सों में बराबर संख्या के साथ तोड़कर काम करता है, और उन्हें फीस्टल नेटवर्क के माध्यम से प्रवाह करता है, अनिवार्य रूप से गोल समारोह के परिणाम के साथ XOR'ing और प्रत्येक पुनरावृत्ति पर हिस्सों को स्वैप करना।

यदि प्रक्रिया के हर चरण में, प्रत्येक आधा 21 बिट्स तक सीमित है तो परिणाम दोनों हिस्सों को 42 बिट्स से अधिक न होने की गारंटी है।

तो यहाँ मेरे प्रस्तावित संस्करण है:

CREATE OR REPLACE FUNCTION pseudo_encrypt42(VALUE bigint) returns bigint 
AS $$ 
DECLARE 
    l1 bigint; 
    l2 bigint; 
    r1 bigint; 
    r2 bigint; 
    i int:=0; 
    b21 int:=(1<<21)-1; -- 21 bits mask for a half-number => 42 bits total 
BEGIN 
    l1:= VALUE >> 21; 
    r1:= VALUE & b21; 
    WHILE i < 3 LOOP 
    l2 := r1; 
    r2 := l1 # (((((1366*r1+150889)%714025)/714025.0)*32767*32767)::int & b21); 
    l1 := l2; 
    r1 := r2; 
    i := i + 1; 
    END LOOP; 
    RETURN ((l1::bigint << 21) + r1); 
END; 
$$ LANGUAGE plpgsql strict immutable; 

इनपुट (2^42)-1 से कम होना चाहिए, अन्यथा outputs pseudo_encrypt42(x) = pseudo_encrypt42(x mod 2^42) के रूप में, भिड़ना होगा।

2^42 और 10^13 के बीच लापता संख्याओं के बारे में क्या किया जा सकता है?

2^42 - 10^13 = 5601953488896 ताकि बहुत सारी संख्याएं गायब हों। मुझे नहीं पता कि फीस्टल नेटवर्क के साथ एक ही पास में उसकी सहायता कैसे करें। एक वर्कअराउंड जो स्वीकार्य हो सकता है, 0..M में अद्वितीय मानों का एक और सेट उत्पन्न करना है और 2^42 जोड़ें, इसलिए टकराव का कोई जोखिम नहीं है।

यह एक और सेट उसी कार्य द्वारा प्राप्त किया जा सकता है, बस ऑफ़सेट जोड़े गए। 4398046511104 + pseudo_encrypt42(x)4398046511104 और 2*4398046511104 = 8796093022208 अद्वितीय मानों के बीच होने की गारंटी है ताकि लक्ष्य के करीब हो। एक ही तकनीक को कई अन्य श्रेणियों के साथ लागू किया जा सकता है, न कि एक ही आकार के जरूरी भी।

हालांकि इस समाधान यादृच्छिक दिखने व्यवहार, के रूप में के बजाय एक भी उत्पादन रेंज जहां हर संख्या 0 और X के बीच हो सकता होने खराब हो, तो आप X/N संख्या के N अलग उत्पादन पर्वतमाला मिल चाहते हैं। इस तरह के कई अलग-अलग विभाजनों के साथ, यह अनुमान लगाना आसान है कि उत्पादन किस विभाजन में होगा, विभाजन के अंदर क्या मूल्य नहीं है।

+1

यह मेरी समस्या हल करता है, धन्यवाद डैनियल! यह एक बहुत ही विस्तृत प्रतिक्रिया है, मुझे यकीन है कि यह अन्य डेवलपर्स के लिए भी बहुत उपयोगी होगा! – MattC

+1

मुझे लगता है कि आपके मामले में इनपुट टकराव से बचने के लिए '(2^21) 'से कम होना चाहिए, क्योंकि आप बाईं ओर के लिए' VALUE >> (64-21) 'का उपयोग कर रहे हैं (यह बाएं से 21 बिट्स लेना है)। इस मामले में '2^21' से अधिक मानों के लिए और कुछ भी कम से कम आप अभी भी बाएं भाग के रूप में शून्य प्राप्त करेंगे लेकिन सही हिस्सा शून्य से फिर से शुरू होगा। इसे ठीक करने के लिए मैंने बाएं हिस्से के लिए 'VALUE >> 21' शिफ्ट का उपयोग किया (यह पहले 21 बिट्स के बाद अगले 21 बिट्स लेने जैसा है) तो आपका प्रतिबंध' (2^42) 'मान्य हो गया। – mopdobopot

+0

@mopdobopot: आप सही हैं, अच्छी पकड़ है। मैंने जवाब में कोड तय कर दिया है। –

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