2012-10-06 10 views
11

लेता है मैं एक ऐसे सिस्टम पर काम कर रहा हूं जो उत्तर # 2 here में यादृच्छिक आईडी उत्पन्न करता है।pseudo_encrypt() plpgsql में फ़ंक्शन जो बिगिन

मेरी समस्या यह है कि उल्लिखित pseudo_encrypt() फ़ंक्शन अंतर्निहित नहीं है। मैंने इसे फिर से लिखने की कोशिश की लेकिन यह हमेशा एक ही परिणाम देता है:

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

क्या कोई इसे जांच सकता है?

उत्तर

16

4294967295 32 बिट्स (4294967296 के बजाय) का चयन करने के लिए बिटमैस्क के रूप में उपयोग किया जाना चाहिए। यही कारण है कि वर्तमान में आपको विभिन्न इनपुट के लिए एक ही मूल्य मिलता है।

मैं भी l2 और r2 के प्रकार के लिए bigint उपयोग करने का सुझाव चाहते हैं, वे वास्तव में, r1 और l1

से अलग नहीं करना चाहिए और बेहतर अनियमितता के लिए, PRNG समारोह में एक बहुत अधिक गुणक का उपयोग पाने के लिए मध्यवर्ती ब्लॉक कि वास्तव में 32 बिट पर कब्जा है, 32767 * 32767 बजाय 32767.

पूरा संशोधित संस्करण की तरह:

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; 

पहले परिणाम:

 
select x,pseudo_encrypt(x::bigint) from generate_series (1, 10) as x; 
x | pseudo_encrypt  
----+--------------------- 
    1 | 3898573529235304961 
    2 | 2034171750778085465 
    3 | 169769968641019729 
    4 | 2925594765163772086 
    5 | 1061193016228543981 
    6 | 3808195743949274374 
    7 | 1943793931158625313 
    8 | 88214277952430814 
    9 | 2835217030863818694 
10 | 970815170807835400 
(10 rows) 
+0

आह bitmask एक मूर्ख गलती थी ... तुम बहुत धन्यवाद बहुत! पूरी तरह से काम करता है! बीटीडब्ल्यू: आप बिगिन का सुझाव देना चाहते थे, int नहीं। –

+0

@ डैनियल वेरेट मुझे फक्शन में क्या संशोधित करना है यदि मुझे 13 अंकों की अधिकतम लंबाई के साथ एक बड़ा अंतर चाहिए? – MattC

+0

@ मैटसी: यह गैर-तुच्छ है, आप इसे एक नए प्रश्न के रूप में सबमिट कर सकते हैं। इसके अलावा इस तकनीक के साथ ऊपरी सीमा '2^एन' होने जा रही है जहां 'एन' एक संख्या भी है, न कि' 10^एन'। –

5

पुराना लेकिन अभी भी एक दिलचस्प सवाल है। डेनियल जवाब मैं, एक थोड़ा संशोधित संस्करण का उपयोग कर रहा है इस के लिए वापसी बयान बदलने के मुकाबले (आर 1 और एल 1 का आदान-प्रदान) के रूप में भी लेख Pseudo encrypt के अंत में उल्लेख किया है:

RETURN ((r1::bigint << 32) + l1); 

इस बदलाव के लिए कारण यह है कि है अंतर्निहित Feistel algorithm को अंतिम दौर के अंत में बाएं दाएं का आदान-प्रदान नहीं करना चाहिए।

pseudo_encrypt(pseudo_encrypt(x) == x // always returns true 

यहाँ pgsql में पूर्ण कोड है:: इस बदलाव के साथ समारोह का अपना उलटा समारोह के रूप में कार्य करने की क्षमता आ

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 ((r1::bigint << 32) + l1); 
END; 
$$ LANGUAGE plpgsql strict immutable; 
संबंधित मुद्दे