Postgresql 减少伪加密函数ouput的长度

Postgresql 减少伪加密函数ouput的长度,postgresql,Postgresql,我有一个关于你的问题。 有没有办法把输出量减少到6?我真的很喜欢这个函数,并想使用它,但只需要输出介于1和999999之间 这个问题涉及到。我想用它来创建介于1和999999之间的unqiue数字 谢谢。使用生成的值生成从开始\u值到结束\u值范围内的数字: select start_value + mod(pseudo_encrypt(number), end_value - start_value + 1); 对于您的情况,这将如下所示: select 1 + mod(pseudo_enc

我有一个关于你的问题。 有没有办法把输出量减少到6?我真的很喜欢这个函数,并想使用它,但只需要输出介于1和999999之间

这个问题涉及到。我想用它来创建介于1和999999之间的unqiue数字

谢谢。

使用生成的值生成从
开始\u值
结束\u值
范围内的数字:

select start_value + mod(pseudo_encrypt(number), end_value - start_value + 1);
对于您的情况,这将如下所示:

select 1 + mod(pseudo_encrypt(23452), 999999);

设定9999999的上限并不十分简单,因为该算法是在比特块上运行的,所以很难摆脱二的幂

您可以通过以下方法解决此问题:只需尝试
encrypt(n)
encrypt(n))
encrypt(encrypt(n))
。。。直到结果在[1999999]范围内为止。为了将迭代次数保持在最小,您需要调整块大小,使其尽可能接近此范围

此版本将允许您指定输入/输出的范围:

CREATE OR REPLACE FUNCTION pseudo_encrypt(
  value INT8,
  min INT8 DEFAULT 0,
  max INT8 DEFAULT (2^62::NUMERIC)-1
) RETURNS INT8 AS
$$
DECLARE
  rounds CONSTANT INT = 3;
  L INT8[];
  R INT8[];
  i INT;
  blocksize INT;
  blockmask INT8;
  result INT8;
BEGIN
  max = max - min;
  value = value - min;
  IF NOT ((value BETWEEN 0 AND max) AND (max BETWEEN 0 AND 2^62::NUMERIC-1)) THEN
    RAISE 'Input out of range';
  END IF;

  blocksize = ceil(char_length(ltrim(max::BIT(64)::TEXT,'0'))/2.0);
  blockmask = (2^blocksize::NUMERIC-1)::INT8;
  result = value;
  LOOP
    L[1] = (result >> blocksize) & blockmask;
    R[1] = result & blockmask;
    FOR i IN 1..rounds LOOP
      L[i+1] = R[i];
      R[i+1] = L[i] # ((941083981*R[i] + 768614336404564651) & blockmask);
    END LOOP;
    result = (L[rounds]::INT8 << blocksize) | R[rounds];

    IF result <= max THEN
      RETURN result + min;
    END IF;
  END LOOP;
END;
$$
LANGUAGE plpgsql STRICT IMMUTABLE;

回答很好,但是当我使用这个选择时,我又遇到了一个独特的问题。很难用9999999条目来测试它,但是当我用例如99来测试它时。我又遇到了unqiue验证问题。
SELECT i FROM generate_series(1,999999) s(i)
EXCEPT
SELECT pseudo_encrypt(i,1,999999) FROM generate_series(1,999999) s(i)