我想生成指定長度的隨機數。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));'? –