PDA

View Full Version : سوال: بهترین الگوریتم برای بهترین استفاده از زمان و فضا



m2011kh
یک شنبه 05 آذر 1396, 02:39 صبح
سلام و خسته نباشید.

راستش من چند روزه دارم روی یه پروژه کار میکنم. من قراره اعمال پایه ریاضی (جمع، ضرب، تقسیم، تفریق) رو روی اعداد حقیقی خیلی بزرگ انجام بدم. من یه کلاس اصلی دارم برای چهار عمل اصلی و چند تا کلاس فرعی که یکیش برای کار روی رشته هاست و یکی دیگه برای تبدیل رشته ها به لیست های مختلف و برعکسش.

راستش کمکی که میخوام زیاد به کد مربوط نمیشه. و اینجا مطرح کردم (نه تو قسمت الگوریتم ها) چونکه مسئله زمان و حافظه ی مورد نیاز تو زبان ها و محیط های مختلف مختلفه و من سی شارپ فقط مد نظرم هست.

فعلا دارم روی تابع ضرب از کلاس اعمال اصلی کار میکنم. یه راه خیلی ساده و کلاسیک اینه که دقیقا همونطور که ما خودمون اعداد رو ضرب میکنید ضرب کنم.
مثلا برای ضرب 99 در 99:

99 99
------------
891
8910
----------------
9801

خب این روش رو پیاده کردم. مسئله خاصی پیش نمیاد تا زمانی که عدد خیلی بزرگ نشه. وقتی که عدد بزرگ بشه حجم لیست ها به طرز وحشتناکی زیاد میشه و خیلی خیلی طول میکشه.
میدونم که به هر حال تغییر زیادی نمیشه توش ایجاد کرد ولی یه اصلاحاتی میشه برای سرعت و حجم مورد نیاز روی RAM انجام داد.

فعلا دوتا ایده به ذهنم رسید. راهنمایی که من از دوستان میخوام اینه که به نظر شما کدوم روش منطقی تره (اصلا دو روش کلا منطقی هست؟) و چرا؟

ایده اول:

دو عدد به تابع به عنوان رشته داده میشه. عدد از وسط نصف میشه و نصفه دوم به صورت برگشتی دوباره به تابع برمیگرده (تابع خودشو صدا میزنه با نصفه ی دوم عدد).و جواب را به جواب نصفه ی خودش جمع میکنه و میشه نتیجه نهایی.
تابع تو دومین باری که صدا میشه دوباره عددو نصف میکنه و دوباره خودشو صدا میکنه. این تا جایی ادامه پیدا میکنه که توی آخرین فراخوانی عدد فقط 1 جایگاه داره و دیگه قابع تبدیل نیست.

خب چرا به نظر من این کار میتونه موثر باشه؟ چون وقتی که تابع از فراخوانی خودش ازاد میشه و برمیگرده به عقب، فراخوانی های آخر بسته میشن و لیست هاشون هم باهاشون از حافظه پاک میشه. فراخوانی های بالا دارن هنوز کار میکنن و حافظه ی اضافه پاک شده.

147146

ایده دوم:

دوباره مثل قبل اعداد از بالا به پایین دو تقسیم میشن ولی با فرق اینکه هم سمت چپ دوباره به تابع با فرخوانی بازگشتی داده میشه و هم سمت راست. اینکار تا جایی که عدد به جایگاه های یکی یکی تقسیم میشه و دوباره تو راه برگشتی فراخوانی ها حافظه های اضافی پاک میشه و همینطور سمت چپ و راست تو دو نخ جدید اجرا میشه که اگه processor هسته های بیشتری داشته باشه سرعت عملیات رو خیلی بالا تر میبره.

147147

البته تمام اینایی که گفتم فعلا فقط فرضیه است. چون که خودم مطمئن نیستم. این فراخوانی پی در پی توابع خودش چقدر فضای حافظه رو اشغال میکنه و اینکه ساخت نخ خودش هم زمان و فضا میخواد.

در واقع الان از شما راهنمایی میخوام که آیا نظرتون در مورد این دو ایده چی هست (مسلما فقط تو C#‎‎ ) و آیا راه بهتری هست؟



موفق و سربلند باشید
محمد مهدی خلیلی

parvizwpf
یک شنبه 05 آذر 1396, 21:07 عصر
جسارتا ما این رو در سی شارپ داریم البته نمیدونم بدرد شما میخوره:
System.Numerics.BigInteger

string positiveString = "91389681247993671255432112000000";
string negativeString = "-90315837410896312071002088037140000";
BigInteger posBigInt = 0;
BigInteger negBigInt = 0;

try
{
posBigInt = BigInteger.Parse(positiveString);
Console.WriteLine(posBigInt);
}
catch (FormatException)
{
Console.WriteLine("Unable to convert the string '{0}' to a BigInteger value.",
positiveString);
}

if (BigInteger.TryParse(negativeString, out negBigInt))
Console.WriteLine(negBigInt);
else
Console.WriteLine("Unable to convert the string '{0}' to a BigInteger value.",
negativeString);

BigInteger result = posBigInt * negBigInt;

Console.WriteLine(result);

Console.ReadKey();