如何产生一个随机数?(50分)

B

bzmouse

Unregistered / Unconfirmed
GUEST, unregistred user!
我在编程时,需一个随机数,请问如何产生?
 
用random。
 
function Random [ ( Range: Integer) ];
Description
Random returns a random number within the range 0 <= X < Range. If Range
is not specified, the result is a real-type random number within the range
0 <= X < 1.
To initialize the random number generator, add a single call Randomize
or assign a value to the RandSeed variable before making any calls to Random.
Note: Because the implementation of the Random function may
change between compiler versions, wedo
not recommend using Random for encryption or other purposes that require reproducible sequences of pseudo-random numbers.
 
有实例吗?
 
使用Random函数。例子:
var
I: Integer;
begin
Randomize;
for I := 1 to 50do
begin
{ Write to window at random locations }
Canvas.TextOut(Random(Width), Random(Height), 'Boo!');
end;
end;
 

象这样的问题你最好是自己解决,查资料,很容易的
这样才能进步呀!
 
不是我有意见,这问题的答案在Delphi的Help里就有。
 
对a,看 help
 
RAMDOM取得并不是真正的随机。
不信的话可以编过程序,
连续取出10个“随机数”,打印出来,
然后程序退出,再启动运行,
我想这两次10个数一定是完全相同的。
 
问得好! Random 函数并不真正随机.
请看: http://www.cn.ibm.com/developerWorks/security/playing/index.shtml
不要觉得这个简单, Code Red 的作者竟然也会犯随机数的错误,
他使得 Code Red 生成的随机攻击 IP 地址, 实际上是一个相同的序列.
所以, 开始的半个月, 被感染的机器实际上在重复攻击相同的 IP, 因而影响并不大.
我记得有种做法是, 先用 Random 生成一个比较大的数组, 再用Random加上什么算法,
到那个数组中去取随机数, 可惜记不清具体怎么做了, 愿意听高手的解答.

 
先要用randomize;初始化才会得到不一样的随机数据
 
try 这个:
本类可用来产生从MinNumber到MaxNumber之间的随机数,只要设定Unique,每个数字就只
使用一次。此外还可以检查数字是否使用过。一个动态的Tbit数组用来保证数字只会返回
一次,并看是否所有的数字都使用过。对牌类游戏等十分有用。从1到52之间的随机数,一
旦用过就不会再抽出相同的牌,直至牌发完。
属性
-----------------
MinNumber
随机数下限
MaxNumber 
随机数上限
NumbersTotal
可用数字总数
NumbersUsed
总体中已用的不重复数字
NumbersFree
总体中未用的不重复数字
Unique
如果设定true值,则数字不会重复使用。如果设成false则数字可以重复使用。
方法
---------------
IsUsed(Index) 当使用UNIQUE并且数字已使用时返回true。
Reset 清除NumbersUsed和NumbersFree (由UNIQUE使用)。
GetRandom返回在MinNumber到MaxNumber之间的随机数。
(如果设定UNIQUE就不会出现重复数字)
// =========================
// 示例
// =========================
procedure TForm1.Button2Click(Sender: TObject);
var R : TRandomEngine;
begin
R := TRandomEngine.Create;
R.MinNumber := 1;
R.MaxNumber := 52;
R.Unique := true;
repeat
Memo1.Lines.Add(inttostr(R.GetRandom) + ' ' +
inttostr(R.NumbersTotal) + ' ' +
inttostr(R.NumbersUsed) + ' ' +
inttostr(R.NumbersFree));
until R.NumbersFree = 0;
R.Free;
end;
delphi delphi3000 文章TRandomEngine 随机
02/20/2001
unit REngine;
interface
uses Windows,Classes;
type
TRandomEngine = class(TObject)
private
FSelected : TBits;
FArrSize,FNumbersUsed : longint;
FMinNumber,FMaxNumber : longint;
FUnique : boolean;
procedure SizeSelArray;
procedure SetFMinNumber(NewValue : longint);
procedure SetFMaxNumber(NewValue : longint);
function GetFNumbersFree : longint;
public
constructor Create;
destructor Destroy;
override;
procedure Reset;
function GetRandom : longint;
function IsUsed(Index : longint) : boolean;
property MinNumber : longint read FMinNumber write SetFMinNumber;
property MaxNumber : longint read FMinNumber write SetFMaxNumber;
property Unique : boolean read FUnique write FUnique;
property NumbersUsed : longint read FNumbersUsed;
property NumbersTotal : longint read FArrSize;
property NumbersFree : longint read GetFNumbersFree;
end;

// ===================================
// 创建和释放对象
// ===================================
constructor TRandomEngine.Create;
begin
FSelected := TBits.Create;
FNumbersUsed := 0;
FMinNumber := 0;
FMaxNumber := 0;
FArrSize := 0;
FUnique := false;
Randomize;
end;

destructor TRandomEngine.Destroy;
begin
inherited Destroy;
FSelected.Free;
end;

// ===========================
// Get/Set方法
// ===========================
procedure TRandomEngine.SetFMinNumber(NewValue : longint);
begin
if (NewValue <> FMinNumber) then
begin
FMinNumber := NewValue;
if FMinNumber > FMaxNumber then
FMaxNumber := FMinNumber;
SizeSelArray;
end;
end;

procedure TRandomEngine.SetFMaxNumber(NewValue : longint);
begin
if (NewValue <> FMaxNumber) then
begin
FMaxNumber := NewValue;
if FMaxNumber < FMinNumber then
FMinNumber := FMaxNumber;
SizeSelArray;
end;
end;

function TRandomEngine.GetFNumbersFree : longint;
begin
Result := FArrSize - FNumbersUsed;
end;

// =======================================
// 调整布尔数组(FSelected)的大小
// =======================================
procedure TRandomEngine.SizeSelArray;
var i : longint;
begin
FArrSize := FMaxNumber - FMinNumber + 1;
if FArrSize > 0 then
begin
FSelected.Size := FArrSize;
for i := 0 to FArrSize - 1do
FSelected := false;
end;

FNumbersUsed := 0;
end;

// =======================================
// 重置可用,已用,未用数字。
// 为IsUsed()重置Fselected数组,
// 使之为false。
// =======================================
procedure TRandomEngine.Reset;
begin
SizeSelArray;
end;

// ===================================================
// 如果已设定Unique,数字已使用,
// 则返回true/false。
// ===================================================
function TRandomEngine.IsUsed(Index : longint) : boolean;
var Retvar : boolean;
begin
if (Index < FMinNumber) or (Index > FMaxNumber) then
Retvar := false
else
RetVar := FSelected[Index - FMinNumber];
Result := RetVar;
end;

// ===================================================
// 根据最小和最大值返回随机数。如果
// 已设定Unique,则根据Fselected数
// 组生成(即保证数字未用过)。
// ===================================================
function TRandomEngine.GetRandom : longint;
var V : longint;
NumSelected : boolean;
begin
if FUnique and (FNumbersUsed = FArrSize) then
V := 0
else
begin
repeat
V := Random(FMaxNumber - FMinNumber + 1) + FMinNumber;
if not FUnique then
NumSelected := true
else
begin
if FSelected[V - FMinNumber] then
NumSelected := false
else
begin
NumSelected := true;
FSelected[V - FMinNumber] := true;
inc(FNumbersUsed);
end;
end;
until NumSelected;
end;

Result := V;
end;

end.
 
对某些自认高手的人表示反感(如5414之流)
在VB中有同样的问题,我也发现,但不成障碍,未仔细研究,在此表示关注
 
不要用randominze了,这样的结果说明,用时钟播种的伪随机数,所有结果不是不可预测的
 
我通常取当前时间的秒数作为我的随机数。不知各位有何看法?
 
我记得《电脑报》介绍网景的程序员在开发Netscape时由于采用了错误的随机数,好像是
通过流失的时间值吧,结果加密系统出现了漏洞被破解!可见随机数的确是一个问题。
 
是啊是啊,是叫伪随机数
好想:turbo c 2.0的随机数也是伪随机数
是不是borland公司的算法一直延续了下来,一直都是这样?
 
Delphi的Random函数有一个问题——每个版本的Delphi的Random函数的随机数产生方法都不一样,
如果你希望用不同版本的Delphi编译出来的程序产生的随机数有“可再现性”,必须自己定义一个
随机函数。
下面是我写的一个例子,献丑了。
unit Crypto;
interface
uses
Windows;
procedure MyRandomize(const RandomSeek,StartNum:Integer);
function MyRandom(const N:DWord):DWord;
implementation
var
RandomSeekNum,NowNum:Integer;
procedure MyRandomize(const RandomSeek,StartNum:Integer);
begin
RandomSeekNum:=RandomSeek xor 2084626433;
NowNum:=StartNum xor 1041592654;
end;
function MyRandom(const N:DWord):DWord;
var
m,m1:Integer;
begin
m:=((DWord(NowNum) and $80000000)shr 31)xor((DWord(NowNum) and $00200000)shr 21)xor((DWord(NowNum) and $00000400)shr 10)xor(DWord(NowNum) and $00000001);
m1:=((DWord(NowNum) and $80500000)shr 21)xor((DWord(NowNum) and $08200000)shr 20)xor((DWord(NowNum) and $00000400)shl 10)xor(DWord(NowNum) and $00000041);
NowNum:=(RandomSeekNum xor m1)+((NowNum shl 1)xor m);
Result:=DWord(NowNum) mod N;
end;

下面的过程用于产生一个随机的文件——如果文件足够大,你就会发现——该文件中各个ASCII码的出现概率完全一样。
uses Crypto;
procedure TForm1.Button1Click(Sender: TObject);
const
BufLength=8192;
var
i,j,n,key,m,Temp:Integer;
Buf:array[1..BufLength] of Byte;
Ay,By:array[0..BufLength-1]of Integer;
FS:TFileStream;
begin
n:=StrToIntDef(Edit1.Text,0);
//随机文件长度(以K为单位)
if n<1024 then
begin
Edit1.Text:='1024';
exit;
end
else
if n>40960 then
begin
Edit1.Text:='40960';
exit;
end;
FS:=TFileStream.Create('Random.dat',fmCreate);
m:=0;
key:=StrToIntDef(Edit2.Text,0);
//随机数种子
for i:=0 to BufLength-1do
By:=1+i;
while n>0do
begin
for i:=0 to BufLength-1do
Ay:=1+(i+n) mod BufLength;
MyRandomize(key-n*2,m xor n);
for i:=0 to BufLength-1do
begin
j:=Integer(MyRandom(BufLength-i))+i;
Temp:=Ay[j];
Ay[j]:=Ay;
Ay:=Temp;
end;
for i:=0 to BufLength-1do
begin
j:=Integer(MyRandom(BufLength-i))+i;
Temp:=By[j];
By[j]:=By;
By:=Temp;
Buf[Ay]:=Temp;
end;
FS.Write(Buf,BufLength);
m:=m+PInteger(@Buf[BufLength-3])^;
Dec(n,BufLength div 1024);
end;
FS.Free;
Close;
end;
 
顶部