복붙노트

[SQL] BIGINT 소요 pseudo_encrypt () 함수 plpgsql

SQL

BIGINT 소요 pseudo_encrypt () 함수 plpgsql

여기 대답 # 2에서와 같이 임의 ID를 생성하는 시스템에서 일하고 있어요.

내 문제는 INT와 상술 pseudo_encrypt () 함수가 작동하는 BIGINT하지 않는 것이있다. 나는 그것을 다시 시도했지만 항상 같은 결과를 반환합니다 :

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;

누군가가이를 확인할 수 있습니까?

해결법

  1. ==============================

    1.4294967295은 (4294967296 대신의) 32 개 비트를 선택하기 위해 비트 마스크로 사용되어야한다. 즉 현재 서로 다른 입력에 대해 동일한 값을받을 이유입니다.

    4294967295은 (4294967296 대신의) 32 개 비트를 선택하기 위해 비트 마스크로 사용되어야한다. 즉 현재 서로 다른 입력에 대해 동일한 값을받을 이유입니다.

    나는 또한 L2와 R2의 유형 BIGINT를 사용하는 것이 좋습니다 것, 그들은 정말 R1과 L1에서 차이가한다

    그리고, 더 나은 임의성에 대한, 정말 32 비트를 차지합니다 32767 * 32767 대신 32767과 같은 중간 블록을 얻기 위해 PRNG 기능에 훨씬 더 높은 배율을 사용합니다.

    전체 수정 된 버전 :

    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)
    
  2. ==============================

    2.올드하지만 여전히 흥미로운 질문입니다. 다니엘스에 비교하는 것은 내가 약간 수정 된 버전을 사용하여이에 return 문을 변경하고 대답으로도 기사 의사의 암호화의 끝 부분에 언급 한 (교환 R1과 L1) :

    올드하지만 여전히 흥미로운 질문입니다. 다니엘스에 비교하는 것은 내가 약간 수정 된 버전을 사용하여이에 return 문을 변경하고 대답으로도 기사 의사의 암호화의 끝 부분에 언급 한 (교환 R1과 L1) :

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

    이러한 변화의 이유는 기본 파이 스텔 알고리즘은 마지막 라운드의 끝에 좌우 교환하지해야한다는 것입니다. 이러한 변화와 함께 함수는 자신의 역 기능의 역할을 할 수있는 능력을 회복 :

    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;
    
  3. from https://stackoverflow.com/questions/12761346/pseudo-encrypt-function-in-plpgsql-that-takes-bigint by cc-by-sa and MIT license