PDA

View Full Version : تولید رمز های عددی غیر تکراری در زمان کم



عقاب سیاه
شنبه 14 آذر 1388, 09:12 صبح
سلام ببخشید جستجو که کردم چندین مورد بود که یکی از بهترین های آن به VB نوشته شده بود و کارایی و قدرت خوبی هم داشت و زمانش هم عالی اما وقتی یکی از دوستان آن را به زبان دلفی تبدیل کرده بودند سرعتش خیلی خیلی کم شده بود.

کاربر نرم فزار تعداد ارقام رمز و تعدا خود رمز هارا مشخص می کند و من باید به صورت تصادفی و غیر تکراری در کم ترین زمان ممکن آنرا بسازم تکه کدی نیز نوشتم اما برای تعداد زیاد خیلی زمان می برد از ترد ها هم استفاده کرم زمانش بیش تر از زمان معمولی شد.

Var I,j,k,a:integer;
begin
Randomize;
while ComboBox1.Items.Count<8000 do Begin
For k:=1 to 8000-ComboBox1.Items.Count do Begin
Randomize;
ComboBox1.Items.Add(IntToStr(Random(9999)));
end;
/// حذف کد های تکراری
while Length(ComboBox1.Items.Strings[0])<4 do
ComboBox1.Items.Delete(0);
for I:=1 to ComboBox1.Items.Count do Begin
A:=1;
for J:=I+1 to ComboBox1.Items.Count do Begin
if (ComboBox1.Items.Strings[I-1]=ComboBox1.Items.Strings[j-A]) or
(Length(ComboBox1.Items.Strings[j-A])<4) then Begin
ComboBox1.Items.Delete(J-A);
A:=A+1;
end;
end;
end;
//////
end;
end;
خوب در کد بالا می خواهیم 8000 کد چهار رقمی غیر تکراری بسازیم و در Combobox1 ذخیره کنیم سپس اعداد تکراری حذف می شوند و به مقدار باقی مانده تا 8000 دوباره شروع به ساخت کد ها می کند و .....
این چرخه تا زمان ساخت 8000 کد غیر نکراری ادامه دارد مشکل من در کارایی نیست در زمان است، برای ساخت مثلا 700 کد چیزی در حدود ثانیه طول می کشد، اما وقتی اعداد بالا می رود زمان بسیار زیادی می خواهد.

ببخشید که سوالم خیلی طول کشید:خجالت: با تشکر از پاسخهایتان:تشویق:

vcldeveloper
شنبه 14 آذر 1388, 10:28 صبح
uses wcrypt2;

function GenerateRandomBytes(Len: Cardinal): TBytes;
var
hProv : HCRYPTPROV;
begin
if not CryptAcquireContext(@hProv,nil,MS_ENHANCED_PROV,
PROV_RSA_FULL,0) then
CryptAcquireContext(@hProv,nil, MS_ENHANCED_PROV,
PROV_RSA_FULL,CRYPT_NEWKEYSET);
if hProv > 0 then
try
SetLength(Result,Len);
Win32Check(CryptGenRandom(hProv,Len,@Result[0]));
finally
CryptReleaseContext(hProv,0);
end;
end;

function BytesToHex(const Bytes: TBytes): string;
var
i : integer;
begin
for i := 0 to Length(Bytes)-1 do
Result := Result + IntToHex(Bytes[i],2);
end;


مثال، کد زیر 8 بایت تصادفی تولید میکنه، و مقدار آنها را به صورت هگزادسیمال نمایش میده:
ShowMessage(BytesToHex(GenerateRandomBytes(8)));

عقاب سیاه
شنبه 14 آذر 1388, 10:57 صبح
uses wcrypt2;
ببخشید دلفی به یونت wcrypt2 ایراد می گیرد و می گوید وجود ندارد!
با تشکر:گریه:

vcldeveloper
یک شنبه 15 آذر 1388, 02:57 صبح
ببخشید دلفی به یونت wcrypt2 ایراد می گیرد و می گوید وجود ندارد!
اون فایل ترجمه header توابع مربوط به رمزنگاری ویندوز هست. فایلش رو به ضمیمه پست قبلی پیوست کردم. از همانجا دانلود کنید.

khoshblagh
دوشنبه 16 آذر 1388, 12:59 عصر
با سلام خدمت جناب کشاورز
خطاهای زیر اعلام میگردد:


[Error] Unit1.pas(29): Undeclared identifier: 'TBytes'
[Warning] Unit1.pas(33): Unsafe code '@ operator'
[Warning] Unit1.pas(35): Unsafe code '@ operator'
[Error] Unit1.pas(39): Incompatible types
[Warning] Unit1.pas(40): Symbol 'Win32Check' is specific to a platform
[Warning] Unit1.pas(40): Unsafe code '@ operator'
[Error] Unit1.pas(51): Incompatible types
[Fatal Error] Project1.dpr(5): Could not compile used unit 'Unit1.pas'


با تشکر

mossaferin
دوشنبه 16 آذر 1388, 16:15 عصر
سلام



خطاهای زیر اعلام میگردد:




Type
TBytes=Array of Byte;


موفق باشی

عقاب سیاه
دوشنبه 16 آذر 1388, 16:28 عصر
با تشکر از آقای کشاورز
اولا من می خواهم فقط اعداد در کد تولید شده باشند که در مثال شما از خروف هم استفاده شده در ضمن در صورت ادامه این چرخه تا 8000 با کد تکراری تولید نمی شود؟
دوما من در مورد اون برنامه VB و ترجمه اش نیز هنز متقاعد نشده ام که چگونه یک کد که در VB چنین سرعتی دارد در دلفی با این افت سرعت روبرو شده است!با یک سرچ کوچک در مورد تولید اعداد تصادفی در بازده مورد نظر می تونید برنامه VB را و در کتابخانه فایلها در قسمت دلفی برنامه ترجمه شده به زبان دلفی را دانلود کنید
-----------------------------------
دوست عزیز khoshblagh کد که مشکلی نداشت من تست کردم و جواب داد!

vcldeveloper
دوشنبه 16 آذر 1388, 23:40 عصر
اولا من می خواهم فقط اعداد در کد تولید شده باشند که در مثال شما از خروف هم استفاده شده در ضمن در صورت ادامه این چرخه تا 8000 با کد تکراری تولید نمی شود؟اون کد بایت های تصادفی تولید میکنه، برای اینکه مقادیر هر بایت قابل نمایش باشه، مقدار هر بابت به هگزا دسیمال تبدیل شده. شما اگر نمیخواید هگزادسیمال داشته باشید، می تونید هر بایت تولیدی را در یک متغیر byte معمولی ذخیره کنید، و باهاش هر کاری که خواستید انجام بدید.

اون تابع کدهای تصادفی مناسب برای رمزنگاری تولید میکنه که از نظر تصادفی بودن، بسیار دقیق تر از مقادیر تصادفی هست که توابع استاندارد تولید اعداد تصادفی در زبان های برنامه نویسی مختلف (مثل C، VB، دلفی، و غیره) تولید می کنند.


دوما من در مورد اون برنامه VB و ترجمه اش نیز هنز متقاعد نشده ام که چگونه یک کد که در VB چنین سرعتی دارد در دلفی با این افت سرعت روبرو شده است!من اطلاعی از برنامه VB ایی که بهش اشاره می کنید، ندارم؛ معلوم هم نیست که این کد دلفی که شما قرار دادید واقعا متناظر با همون کد VB باشه.


خطاهای زیر اعلام میگردد:به خاطر این هست که از نسخه های قدیمی دلفی (مثل دلفی 7) استفاده می کنید. در اون نسخه ها باید خودتون TByte را با همان شکلی که در پست شماره 6 تاپیک مطرح شد، تعریف کنید.

Hadi_Fayyaz
سه شنبه 17 آذر 1388, 11:50 صبح
سلام دوست عزيز
ضمن تائيد فرمايشات جناب كشاورز بايد بگم اشكال كار در سرعت دلفي نيست بلكه در نوع الگوريتمي هست كه شما استفاده كرديد
تابع زير در حدود يك دهم ثانيه زمان 8000 كد غير تكراري و تصادفي توليد ميكنه

procedure TForm1.Button1Click(Sender: TObject);
Var
Rand : Array[1000..9999] of Integer;
I,Temp:Integer;
Enow : Boolean;
Start:Longint;
begin
Start:=GetTickCount;
Enow:=False;
For i:=1000 To 9999 do
Rand[i]:=0;
I:=0;
Randomize;
While Not Enow Do
Begin
Temp:=Random(8999)+1000;
If Rand[temp] = 0 then
Begin
Rand[temp]:=Temp;
I:=I+1;
Combobox1.Items.Add(InttoStr(Temp));
End;
If I>=8000 then
Enow:=True;
End;
Label1.Caption:=InttoStr(GetTickCount-Start);
end;

عقاب سیاه
سه شنبه 17 آذر 1388, 15:38 عصر
با تشکر خیلی زیاد از آقای کشاورز و آقای فیاض :لبخند:

آقای فیاض کد شما خیلی خوب و عالی بود حالا اگر من بخواهم که پویا باشد یعنی رقم اعداد تولید شده را کاربر مشخص کند باید چه کار کنم؟؟؟

راستش فقط با این خط مشکل دارم و نمی دانم چگونه باید این مقدار را از کاربر دریافت کنم!؟

Var
Rand : Array[10000..99999] of Integer;

Hadi_Fayyaz
چهارشنبه 18 آذر 1388, 07:43 صبح
سلام دوست گرامي
خوب اگه بزرگترين و كوچكترين عددي كه ممكنه كاربرت وارد كنه رو ميدوني اونوقت ميتوني Array رو بر حسب اون اعداد تنظيم كني ولي راه اصولي تر استفاده از لينك ليست هست كه يه نمونه برنامه برات ميگذارم
لازم به ذكره كه از تابع بازگشتي استفاده نكردم چون سرعت رو كم ميكنه. در ضمن اگه قراره اين كار مكررا توسط كاربر انجام بشه بايد توجه داشته باشي كه هر بار بايد لينك ليست رو تخريب كني و آيتم هاي comboBox رو هم پاك كني تا كار از اول شروع بشه
موفق باشيد

عقاب سیاه
چهارشنبه 18 آذر 1388, 14:34 عصر
خیلی ممنون از شما
ولی می خواستم بدونم استفاده از Array های بالا مثلا ده رقمی باعث افت سرعت می شود؟

Hadi_Fayyaz
چهارشنبه 18 آذر 1388, 18:33 عصر
سلام دوست من
ببينيد اين تعداد رقم اعداد شما نيست كه باعث كاهش سرعت ميشود بلكه اين تعداد اعداد تصادفي هست كه باعث كاهش سرعت ميشه. شما تو همون برنامه اي كه من براتون فرستادم هرچه تعداد اعداد توليد شده رو. بالا ببريد زمان بيشتري صرف خواهد شد.

اما اينكه من از لينك ليست استفاده كردم به خاطر اين بود كه كاربر شما تو هر محدوده اي كه بخواهد عدد توليد كند بتواند. اما اگر شما ميدونيد كه ممكنه محدوده توليد اعداد شما به 10 رقم هم برسه اونوقت بايد بگم كه ديگه شما از Array نميتونيد استفاده كنيد چون ابعاد Array رو نميتونيد 9999999999 انتخاب كنيد.
ولي در كل اين نكته رو بدونيد كه هرجايي كه بشه از Array استفاده كرد بهتره از Array استفاده كنيد چون سرعت بهتري داره. استفاده از لينك ليست فقط جايي بدرد ميخوره كه واقعا ندونيم با چه تعداد داده سر و كار داريم.
موفق باشيد:لبخندساده: