我想生成指定长度的随机数。delphi生成随机PIN码
function _RandomCode(const CodeLen: Word): Word;
begin
Result := Random(CodeLen);
repeat
Result := Result + Random(CodeLen) + 1;
until (Length(IntToStr(Result)) = CodeLen)
end;
结果总是10000
我想生成指定长度的随机数。delphi生成随机PIN码
function _RandomCode(const CodeLen: Word): Word;
begin
Result := Random(CodeLen);
repeat
Result := Result + Random(CodeLen) + 1;
until (Length(IntToStr(Result)) = CodeLen)
end;
结果总是10000
虽然我投票决定关闭这个问题作为一个重复,再一想这里有问题,使得它不同于纯粹的随机函数应用程序。
首先,你的代码不给你期待的结果,因为你是添加小数字(0 .. codelen-1)的结果每个循环中,当值达到的值停止的是,当转换为字符串时,包含codelen
个字符。对于codelen = 5
,这将始终停止在10000 .. 10003.如果您要在调试器中加入代码,您很快就会意识到为什么您获得了您所做的结果。其次,在@MichaelVincent的启发下,PIN码通常允许前导零,f.ex。 '0123'。因此,我也认为在这个问题上也是如此。因为整型结果不能保存前导零,所以我建议你使用string
型结果。
只在应用程序启动时调用Randomize
一次。
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;
我改变了函数的名称以反映它返回一个字符串。
添加对请求:
关于Randomize
函数(或分配RandSeed
)。它在文档中有解释:
随机初始化内置随机数发生器,随机值为 (从系统时钟获得)。随机数 生成器应通过调用Randomize或 赋值给RandSeed来初始化。
不要将调用与随机函数的调用结合起来调用随机函数,并调用 随机函数。通常,在调用Random之前,只调用一次Randomize。
如果你把_RandomCodeStr
功能在一个单独的单元,你可以把呼叫Randomize
在单位initialization
部分。
你拿起了我在我的评论问题中得到的东西:D –
你能解释为什么我应该在应用程序启动时调用'Randomize'而不是在函数本身内调用它。因为我想把这个功能放在单独的单元中,每当我需要它时调用它,并且在每个应用程序中摆脱调用'Randomize' – RepeatUntil
@RepeatUntil我编辑了有关'Randomize'的回答,以及如何在您计划的单元中调用一次把它塞进去。 –
除了使用randomize
(但只有一次!)为指向的汤姆Brunberg
1)随机两点需要注意是不是密码安全PRNG,所以用它产生随机(如在不可预知的情况下)PIN码是相当不恰当的想法。
2)你的循环速度慢,甚至不太安全(通过连续多次调用Random,导致其统计量累积降低随机性)。 它可能是不确定的。如果一个时刻的长度会比CodeLen多?它永远不会缩小,循环永远不会结束;直到至少整数边界绕回。
使之显得有些更好的,你可以那样做:
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
值不word
值的函数。
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;
你会做什么,例如_RandomCode(4) = 25
?您将不得不在该功能以外的任何位置使用零填充PIN码!最好在功能内进行一次。
在第二个代码中,对于Codelen,j:= 0似乎是一次太多。使用'codelen = 1''i'将变为100,IOW,返回值为0 .. 99 –
@TomBrunberg正确。固定。 –
您的代码失败的原因:您要添加较小的值(1..5),直到数字位数达到5为止。总是得到10000的原因是您在启动时从未调用过Randomize
。这意味着你的“随机”系列总是一样的。
使用RandomRange代替:
返回指定范围内的随机整数。
RandomRange返回从AFrom和ATo(非包含)之间延伸的范围内的随机整数。 RandomRange可以处理负范围(其中AFrom大于ATo)。
要初始化随机数生成器,请在调用RandomRange之前添加一个调用Randomize或将值分配给RandSeed变量。
function _RandomCode(const CodeLen: Word): Cardinal;
// CodeLen is 1,2,3 etc.
begin
Result := RandomRange(0,Trunc(IntPower(10,CodeLen)));
end;
我假定前导零是在PIN码可以接受的,否则所述第一参数设定为适当的值(IntPower(10,CodeLen-1))。
要转换一些固定长度和可能的前导零的字符串,使用:
Format('%.*d',[CodeLen,_RandomCode(CodeLen)])
“Random”返回一个整数X,比如0 <= X
有些问题:'Random(intvalue)'给出整数; RandomRange不包括ATo,所以'-1'是多余的;作者一定要'Codelen = 1,2,3,4,5',而不是十个权力。 – MBo
CodeLen其实不是CodeLen,更好的计算方法是 –
可能的重复的[在delphi中生成随机数](http://stackoverflow.com/questions/34481987/generate-random-number-in-delphi) –
如果codelen是,比方说,4.会返回一个值0007可以接受吗?即7个前导零。或者你只在1000到9999之间寻找数字? –
随机(4)可以是0,1,2或3.为什么不简单:'Result:= Random(IntPow(10,CodeLen));'? –