我正在开发一个生成随机ID的系统,如答案#2
here.
我的问题是,所提到的pseudo_encrypt()函数使用int not 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;
有人可以检查一下吗
4294967295必须用作位掩码来选择32位(而不是4294967296).
这就是为什么目前您为不同投入获得相同价值的原因.
原文链接:https://www.f2er.com/postgresql/191691.html这就是为什么目前您为不同投入获得相同价值的原因.
我还建议使用bigint的类型为l2和r2,它们不应该真的不同于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)