delphi生成随机PIN码

delphi生成随机PIN码,delphi,Delphi,我想生成指定长度的随机数 function _RandomCode(const CodeLen: Word): Word; begin Result := Random(CodeLen); repeat Result := Result + Random(CodeLen) + 1; until (Length(IntToStr(Result)) = CodeLen) end; 结果总是10000使用随机化(但只有一次!!!)将两个音符分开,正如Tom Brunberg所指出

我想生成指定长度的随机数

function _RandomCode(const CodeLen: Word): Word;
begin
  Result := Random(CodeLen);
  repeat
    Result := Result + Random(CodeLen) + 1;
  until (Length(IntToStr(Result)) = CodeLen)
end;

结果总是
10000

使用
随机化
(但只有一次!!!)将两个音符分开,正如Tom Brunberg所指出的那样

1) Random不是加密安全的PRNG,因此使用它生成随机(如不可预测的)PIN码是相当不恰当的想法

2) 您的循环既慢又不安全(通过连续多次调用Random,您会导致其统计数据累积,从而降低随机性)。 而且它可能是不确定的。如果一瞬间的长度超过了科德伦呢?它永远不会收缩,循环永远不会结束;至少在整数边界环绕之前

要使其更好,您可以这样做:

function _PseudoRandomCode(const CodeLen: Word): Word;
var s: string; i: integer; c: char;
begin
  SetLength(s, CodeLen); 
  for i := 1 to CodeLen do begin
    c := '0';
    Inc( c, random(10) ); // + 0..9
    s[i] := c;
  end;
  Result := StrToInt(s);
end;
还是那样

function _PseudoRandomCode(const CodeLen: Word): Word;
var i,j: integer; 
begin
  i := 1; // 10^0
  for j := 1 to CodeLen do
      i := 10 * i; 
  // now i = 10^(CodeLen+1) that is '1' and CodeLen of zeroes.

  Result := Random( i );
end;
虽然我最好让返回
string
value的函数不要
word
value

function _PseudoRandomCode(const CodeLen: Word): String;
var s: string; i: integer; c: char;
begin
  SetLength(s, CodeLen); 
  for i := 1 to CodeLen do begin
    c := '0';
    Inc( c, random(10) ); // + 0..9
    s[i] := c;
  end;
  Result := s;
end;

function _PseudoRandomCode(const CodeLen: Word): string;
var i,j: integer; 
begin
  i := 1; // 10^0
  for j := 1 to CodeLen do
      i := 10 * i; 
  // now i = 10^(CodeLen+1) that is '1' and CodeLen of zeroes.

  Result := IntToStr(Random( i ));
  if Length(Result) < CodeLen then
    Result := StringOfChar('0', CodeLen - Length(Result)) + Result;
end;
function\u伪随机码(const-CodeLen:Word):字符串;
var-s:字符串;i:整数;c:半焦;
开始
设定长度(s,CodeLen);
对于i:=1到CodeLen do begin
c:='0';
Inc(c,random(10));/+0..9
s[i]:=c;
结束;
结果:=s;
结束;
函数_伪随机码(const-CodeLen:Word):字符串;
var i,j:整数;
开始
i:=1;//10^0
对于j:=1到CodeLen do
i:=10*i;
//现在i=10^(CodeLen+1),即“1”和零的CodeLen。
结果:=IntToStr(随机(i));
如果长度(结果)

例如,当RandomCode(4)=25时,您会怎么做?您将不得不在每个使用PIN码的地方,在该函数的外部用零填充PIN码!最好在函数中设置一次。

使用Tom Brunberg指出的
随机化将两个音符分开(但仅一次!!!)

1) Random不是加密安全的PRNG,因此使用它生成随机(如不可预测的)PIN码是相当不恰当的想法

2) 您的循环既慢又不安全(通过连续多次调用Random,您会导致其统计数据累积,从而降低随机性)。 而且它可能是不确定的。如果一瞬间的长度超过了科德伦呢?它永远不会收缩,循环永远不会结束;至少在整数边界环绕之前

要使其更好,您可以这样做:

function _PseudoRandomCode(const CodeLen: Word): Word;
var s: string; i: integer; c: char;
begin
  SetLength(s, CodeLen); 
  for i := 1 to CodeLen do begin
    c := '0';
    Inc( c, random(10) ); // + 0..9
    s[i] := c;
  end;
  Result := StrToInt(s);
end;
还是那样

function _PseudoRandomCode(const CodeLen: Word): Word;
var i,j: integer; 
begin
  i := 1; // 10^0
  for j := 1 to CodeLen do
      i := 10 * i; 
  // now i = 10^(CodeLen+1) that is '1' and CodeLen of zeroes.

  Result := Random( i );
end;
虽然我最好让返回
string
value的函数不要
word
value

function _PseudoRandomCode(const CodeLen: Word): String;
var s: string; i: integer; c: char;
begin
  SetLength(s, CodeLen); 
  for i := 1 to CodeLen do begin
    c := '0';
    Inc( c, random(10) ); // + 0..9
    s[i] := c;
  end;
  Result := s;
end;

function _PseudoRandomCode(const CodeLen: Word): string;
var i,j: integer; 
begin
  i := 1; // 10^0
  for j := 1 to CodeLen do
      i := 10 * i; 
  // now i = 10^(CodeLen+1) that is '1' and CodeLen of zeroes.

  Result := IntToStr(Random( i ));
  if Length(Result) < CodeLen then
    Result := StringOfChar('0', CodeLen - Length(Result)) + Result;
end;
function\u伪随机码(const-CodeLen:Word):字符串;
var-s:字符串;i:整数;c:半焦;
开始
设定长度(s,CodeLen);
对于i:=1到CodeLen do begin
c:='0';
Inc(c,random(10));/+0..9
s[i]:=c;
结束;
结果:=s;
结束;
函数_伪随机码(const-CodeLen:Word):字符串;
var i,j:整数;
开始
i:=1;//10^0
对于j:=1到CodeLen do
i:=10*i;
//现在i=10^(CodeLen+1),即“1”和零的CodeLen。
结果:=IntToStr(随机(i));
如果长度(结果)

例如,当RandomCode(4)=25时,您会怎么做?您将不得不在每个使用PIN码的地方,在该函数的外部用零填充PIN码!最好在函数中设置一次。

代码失败的原因是:添加小值(1..5),直到位数达到5为止。您总是得到10000的原因是,您在启动时从未调用过一次随机化。这意味着您的“随机”序列总是相同的

改用:

返回指定范围内的随机整数

RandomRange返回从AFrom和ATo之间扩展的范围中的随机整数(不包括在内)RandomRange可以处理负范围(其中AFrom大于ATo)

要初始化随机数生成器,请在调用RandomRange之前,添加一个调用Randomize或为RandSeed变量赋值

我假设PIN码中的前导零是可以接受的,否则将第一个参数设置为合适的值(IntPower(10,CodeLen-1))

要将具有固定长度和可能的前导零的数字转换为字符串,请使用:

Format('%.*d',[CodeLen,_RandomCode(CodeLen)])

代码失败的原因:您正在添加小值(1..5),直到位数达到5。您总是得到10000的原因是,您在启动时从未调用过一次随机化。这意味着您的“随机”序列总是相同的

改用:

返回指定范围内的随机整数

RandomRange返回从AFrom和ATo之间扩展的范围中的随机整数(不包括在内)RandomRange可以处理负范围(其中AFrom大于ATo)

要初始化随机数生成器,请在调用RandomRange之前,添加一个调用Randomize或为RandSeed变量赋值

我假设PIN码中的前导零是可以接受的,否则将第一个参数设置为合适的值(IntPower(10,CodeLen-1))

要将具有固定长度和可能的前导零的数字转换为字符串,请使用:

Format('%.*d',[CodeLen,_RandomCode(CodeLen)])

尽管我投票以重复的方式结束了这个问题,但再考虑一下,这里有一些方面使它不同于纯随机函数应用程序

function _RandomCodeStr(const CodeLen: Word): string;
var
  n: integer;
begin
  SetLength(Result, CodeLen);
  for n := 1 to CodeLen do
    Result[n] := Char(ord('0')+ Random(10));
end;
首先,您的代码没有给出预期的结果,因为您正在为每个循环的结果添加小数字(0..codelen-1),当值达到一个值时停止,该值在转换为字符串时包含
codelen
字符数。对于
codelen=5
这将始终在10000处停止。。10003如果您已经在调试器中逐步完成了代码,那么您很快就会意识到为什么会得到