-
ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
با سلام خدمت دوستان.
با اینکه میدونیم اصطلاح رند کردن مخصوص اعداد اعشاریه .اما در اینجا مبحث بنده در مورد ساخت تابعی سفارشی هست که بتونیم اعداد صحیح رو رند یا گرد کنیم.
در برنامه ای دیدم که از کاربر یه مقدار عددی میگرفت. این عدد ماکسیمم گرد سازی بود ... یعنی اینکه:
کاربر وقتی عدد 50 رو مینوشت ، برنامه اینطور عمل میکرد که 50 رو تقسم بر 2 میکرد و عدد صحیحی مورد استفاده در روال برنامه اگه کمتر از 25 بود صفر در نظر میگرفت و بالای اون رو 50 در نظر میگرفت.
جالبتر این بود که این عدد (یعنی عدد ماکسیمم برای رند سازی )قابل تغییر بود.
به عبارت دیگر و برای روشن شدن بیشتر سوال یه مثال میزنم.
مثلا عدد 123 رو 100 میشه.
عدد 166 رو 150 میشه.
عدد 177 رو 200 میشه.
بنده تابعی برای رند کردن تا عدد 50 رو نوشتم. مشکلم اینه چطوری این روش رو برای همه اعداد بتونم تعمیم بدم.
ممنون از راهنماییتون.
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
تابع زیر رو ببینید :
function RoundIt(N, Step : Integer) : Integer;
begin
if (N mod Step) >= (Step / 2) then
N := N - (N mod Step) + Step
else
N := N - (N mod Step);
Result := N;
end;
عدد اصلی رو میگیره به همراه یک عدد دیگه به عنوان " گام ! " رند کردن ، مثلا حاصل ورودیهای 255 و 100 میشه 300 ، یا حاصل ورودی های 223 و 50 میشه 200
روش کار هم به این صورته که عدد اصلی بر عدد " گام ! " تقسیم میشه ، و باقیماندش با نصف " گام ! " مقایسه میشه ، اگر بزرگتر بود ، عدد اصلی از باقیمانده کم میشه و با " گام ! " جمع میشه ، اگر هم بزرگتر نبود عدد اصلی از باقیمانده ی تقسیم بر عدد " گام ! " کم میشه
* عملگر mod باقیمانده ی تقسیم رو به ما میده
موفق باشید ...
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
سلام
من از تابع زیر تو قسمت صندوق یه نرم افزار استفاده کردم
function Gerd(N: Longint; Taghrib: Word): Longint;
var
M: Longint;
begin
if (N <= Taghrib) then
begin
Gerd := N;
Exit;
end;
M := N mod Taghrib;
if M > (Taghrib div 2) then N := ((N div Taghrib) * Taghrib) + Taghrib
else
if M < (Taghrib div 2) then N := (N div Taghrib) * Taghrib;
Gerd := N;
end;
این تابع یه مقدار ورودی (N) و یه عدد برای گرد کردن (Taghrib) دریافت میکنه و مقدار ورودی رو نسبت به اون گرد میکنه. اگه مقدار ورودی به عدد گرد کردن نزدیک باشه به سمت بالا گردش میکنه وگرنه به سمت پایین.
مثلاً اگه قرار باشه اعداد رو با تقریب کمتر از 50 گرد کنیم
1001 میشه 1000
1012 میشه 1000
1024 میشه 1000
1025 میشه 1025
1026 میشه 1050
1049 میشه 1050
1099 میشه 1100 و ...
اما اگه بخواین اعداد ورودی فقط به سمت پایین گرد بشن، میتونید قسمتهای قرمز رنگ رو حذف کنید
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
با تشکر از دو عزیز
جناب Mahmood_N:
وقتی از تابعی که زحمت کشیدید و نوشتیم استفاده میکنیم اگر مقدار گام رو 25 قرار بدیم
عدد 1237 چرا میشه 1225 در صورتی که قرار بود بشه 1250.
مشکل کجاست.
ممنون.
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
دلیلش این بود که 25 عدد فرد هست و حاصل تقسیمش بر دو یک عدد اعشاری میشه ( 12.5 ) ، در حالی که باقیمانده ی تقسیم 1237 بر 25 میشه 12 و در اینصورت شرط برقرار نمیشه ، تصحیح شد :
function RoundIt(N, Step : Integer) : Integer;
begin
if (N mod Step) >= (Step div 2) then
N := N - (N mod Step) + Step
else
N := N - (N mod Step);
Result := N;
end;
* دستور DIV خارج قسمت تقسیم رو به ما میده ( بو صروت یک عدد صحیح )
موفق باشید ...
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
با سلام
ممنون از توجهتون.
یه سوال دیگه داشتم. و اینکه
گام رو باید روی چند بزارم که اگه وارد کردم 124 بشود 120
اگه وارد کردم 125 بشه 125
اگه وارد کردم 126 بشود 150.
ممنون.
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
نمیشه که 124 بشه 120 و 126 بشه 150 ، 124 میشه 120 و 126 میشه 130 اگر گام رو 10 بزارید ، باید نصف گام رو در نظر بگیرید ، اعداد به نصف عددی که برای گام وارد میشه رند می شن
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
شرمنده اشتباه گفتم.(بی دقتی از بنده بود)
گام رو باید روی چند بزارم که اگه وارد کردم 124 بشود 100
اگه وارد کردم 125 بشه 125
اگه وارد کردم 126 بشود 150.
ممنون.
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
سلام
نقل قول:
نوشته شده توسط
Gold
شرمنده اشتباه گفتم.(بی دقتی از بنده بود)
گام رو باید روی چند بزارم که اگه وارد کردم 124 بشود 100
اگه وارد کردم 125 بشه 125
اگه وارد کردم 126 بشود 150.
ممنون.
کدی من گذاشتم دقیقاً همین طور عمل میکنه. (گام باید 50 باشه)
اصولاً استفاده از دو تا دستور If هم بخاطر همین هست که اگه باقیمانده بزرگتر بود یه جور محاسبه بشه، اگه کوچکتر بود یه جور دیگه محاسبه بشه و در غیر اینصورت (مساوی بودن باقیمانده با گام) هیچ محاسبهای انجام نشه.
شما با این توضیح میتونید کد جناب Mahmood_N رو به شکل دلخواه (با تبدیل =< به < و اضافه کردن یه If دیگه) تغییر بدین.
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
ممنون از توجهتون.
کد شما اعدادی که به 12 ختم میشه رو نمیتونه گرد کنه.
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
نقل قول:
وقتی از تابعی که زحمت کشیدید و نوشتیم استفاده میکنیم اگر مقدار گام رو 25 قرار بدیم
عدد 1237 چرا میشه 1225 در صورتی که قرار بود بشه 1250.
مشکل کجاست.
نقل قول:
دلیلش این بود که 25 عدد فرد هست و حاصل تقسیمش بر دو یک عدد اعشاری میشه ( 12.5 ) ، در حالی که باقیمانده ی تقسیم 1237 بر 25 میشه 12 و در اینصورت شرط برقرار نمیشه ، تصحیح شد :
ببخشید به نظرم کل مسیری که این تاپیک طی کرده یکم مشکل داره، اگه اجازه بدید یکم افاضات ریاضی بکنم.
ببینید وقتی ما میگیم "گرد کردن" یا "رند کردن" خوب منظور یه مفهموم ریاضیه موجوده، ما یه گرد گردن داریم که معنیش اینه که یه عدد اعشاری رو می خوایم به ترتیبی به یک عدد صحیح تبدیل کنیم که اگه قسمت اعشاری اون به صفر نزدیکتر بود، حاصل قسمت صحیح ورودی باشه و در صورتی که قسمت اعشاری به یک نزدیک تر بود، حاصل قسمت صحیح ورودی به اضافه یک باشه. حالا اگه نتونیم بگیم قسمت اعشاری به صفر نزدیک تره یا به یک، یعنی اعشار عدد ما دقیقا برابر 0.5 باشه، دیگه باید خودمون یه تصمیمی بگیریم. مثلا توی کد اول آقا محمود تصمیم بر این بوده که در این شرایط همیشه به بالا گرد بشه. ولی رایج اینه که در این شرایط نیمی از ورودی ها به بالا و نیم دیگه به پائین گرد بشن، مثلا فرد یا ذوج بودن قسمت صحیح ملاک خوبی برای این تصمیم گیریه. اینو یه نگاه بکنید، اعداد مختلف با اعشار 0.5 وارد کنید:
Caption := IntToStr(Round(StrToFloatDef(Edit1.Text, 0.0)))
حالا ما یه سری مفاهیم دیگه داریم تحت عنوان "گرد به بالا" و "گرد به پائین" که دیگه مشخصن و اون دنگ و فنگ بالا رو ندارن. معادل اونها در دلفی هم Ceil و Floor هستند که توی Math تعریف شدن.
حالا در مورد مسئله موجود ما می خوایم بازه یا گام گرد کردن رو از 0 .. 1 به 0 .. Step تغییر بدیم. اگه فرض بر حفظ مفاهیم بالا باشه ساده ترین جواب اینه:
function RoundToRange(Value, Range: Integer): Integer;
begin
if Range = 0 then
raise Exception.Create('Range can not be zero!');
Result := Round(Value / Range) * Range;
end;
که حالا با توجه به کاربرد به جای Round میشه از Ceil یا Floor هم به همین شکل استفاده کرد.
تابعی هم که آقا محمود قرار دادن تصور می کنم برهمین اساس پیاده شده و من فکر می کنم کد اول ایشون صحیح و کد دوم دقیقا اشتباه هست.
نقل قول:
وقتی از تابعی که زحمت کشیدید و نوشتیم استفاده میکنیم اگر مقدار گام رو 25 قرار بدیم
عدد 1237 چرا میشه 1225 در صورتی که قرار بود بشه 1250.
ببینید بر اساس اون تعریفی که گفتم جواب صحیح با این وردودی ها دقیقا 1225ه. چون 12 به صفر نزدیکتره تا 25. حالا من نمی دونم با تبدیل ملاک تصمیم گیری از 12.5 به 12 دقیقا چیکار کردیم؟:متفکر: نتیجه میشه:
نقل قول:
کد شما اعدادی که به 12 ختم میشه رو نمیتونه گرد کنه.
حالا دوباره برگردیم سر صورت مسئله:
نقل قول:
گام رو باید روی چند بزارم که اگه وارد کردم 124 بشود 100
اگه وارد کردم 125 بشه 125
اگه وارد کردم 126 بشود 150.
ببینید این چیزی که شما می خواید تابع گرد کردن نیست، یه تابع دیگست. این تابع دقیقا توی اون شرایطی که گفتم باید خودمون تصمیم بگیریم اینطور تصمیم میگیره که در شرایط مرزی اصلا بیخیال گرد کردن بشه. که مثلا اینجوری میشه:
function MyRoundToRange(Value, Range: Integer): Integer;
begin
if Range = 0 then
raise Exception.Create('Range can not be zero!');
if (Value mod Range) = Range / 2 then
Result := Value
else
Result := Round(Value / Range) * Range;
end;
البته بازه با توجه به شرایط مسئله شما 50 میشه.
حالا برای رسیدن به کارایی بیشتر میشه یه بخشی از این کارهارو به جای تقسیم های اعشاری با تقسیم های صحیح پیاده کرد، که دیگه همون div و mod و غیرست که اگه مورد استفادتون پردازش سنگینی نیست لزومی نداره.
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
فکر میکنم تصمیم گیری در این مورد که تابع مورد نظر ما در صورتی که به وسط گام داده شده برسه ، چه عکس العملی نشون بده ، کاملا بستگی به هدف تابع داره ! ، ابتدا باید مشخص کنیم که صرفا می خوایم تابعی بنویسیم که عدد داده شده رو بر اساس قوانین ریاضی در رنج دلخواهی گرد کنه یا اینکه هدف دیگه ای داریم ، مثلا گرد کردن هزینه ی محاسبه شده در یک نرم افزار مثلا حسابداری ! ، در مورد هزینه ، اگر فرض کنیم که بخوایم در گام 100 تومان ، یک هزینه ی محاسبه شده رو گرد کنیم ، این دقیقا سازنده و یا استفاده کننده از نرم افزار هست که مشخص میکنه که ورودی 150 ، بشه 200 یا بشه 100 نه قوانین ریاضی !
تا اینجا راه حلها داده شد و روش انجام کار هم بیان شد ، الآن دیگه تصمیم گیری در این زمینه به خود استفاده کننده از تابع بستگی داره ...
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
ممنون از دو دوست عزیز.
آقا محمود عزیز و دوست خوبم SAASTN بابت افاضات ریاضی جالبشون.
واقعا برام جالبه که با یه معادله کوچیک مثله Result := Round(Value / Range) * Range یه همچین گرد سازی رو میشه انجام داد.
فکر میکنم بنده یه مقدار سوالم رو اشتباه توضیح دادم.
ببینید:
فکر میکنم عددی رو که به عنوان گام در نظر میگیریم باید حد وسط گام باشه. نه ماکسیمم گام.
اگه اینطور باشه جوای سوله من درست در میاد.
مثلا اگه عدد گام رو بزاریم روی 20 :
عدد 19 میشه 0
عدد 20 میشه 20
عدد 21 میشه 40
یا
اگه گام رو یزاریم روی 25
عدد 24 بشه 0
عدد 25 بشه 25
عدد 26 بشه 50
حالا تابعی رو که براا گرد سازی به این ترتیبه رو چطور باید نوشت.
یه تابع نوشتم . اما مشکلم اینه که اگه گام رو بزاریم روی 25 (البته منظور گام حد وسطه) چون تقسیم بر 2 میکردم یه عدد اعشاری در میاد.که محاسبات رو میریزه به هم.
نظرتون راجع به این تابع چیه؟
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
نقل قول:
فکر میکنم تصمیم گیری در این مورد که تابع مورد نظر ما در صورتی که به وسط گام داده شده برسه ، چه عکس العملی نشون بده ، کاملا بستگی به هدف تابع داره !
شکی در این مورد نیست، اون افاضه پرا کنی هایی که کردم فقط برای ایجاد یه مسیر به تابع نهایی بود، فقط این که بگم تابعی که ما می خوایم به چی شبیه تره و با چه تغییراتی تو توابع موجود می تونیم به جواب برسیم.
نقل قول:
حالا تابعی رو که براا گرد سازی به این ترتیبه رو چطور باید نوشت.
همون کد آخری که قرار دادم یعنی تابع MyRoundToRange دقیقا همین کار رو می کنه.
نقل قول:
فکر میکنم بنده یه مقدار سوالم رو اشتباه توضیح دادم.
مگه مثالایی که الان گذاشتین شبیه به این یکی نیست؟
نقل قول:
گام رو باید روی چند بزارم که اگه وارد کردم 124 بشود 100
اگه وارد کردم 125 بشه 125
اگه وارد کردم 126 بشود 150.
نقل قول:
عدد 19 میشه 0
عدد 20 میشه 20
عدد 21 میشه 40
همون تابع MyRoundToRange رو به ازای 19، 20 و 21 و با گام 40 امتحان کنید. برای اون یکی مثال هم همین تابع رو با 24، 25 و 26 و با گام 50 امتحان کنید.
من که اینجوری تست کردم جواب میده:
Caption := IntToStr(MyRoundToRange(StrToIntDef(Edit1.Text, 0), StrToIntDef(Edit2.Text, 1)))
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
ممنون از دوست خوبم SAASTN
ببینید :
نمیدونم اشتباه از منه یا مشکل از جای دیگست.
کد زیر رو نگاه کنید. نمیدونم چرا در هر حالت 1320 میشه در صورتی که قرار بود جواب 1300و1320و1340 شود.
ShowMessage(IntToStr(MyRoundToRange(1319,40)));
ShowMessage(IntToStr(MyRoundToRange(1320,40)));
ShowMessage(IntToStr(MyRoundToRange(1321,40)));
با تشکر.
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
نقل قول:
کد زیر رو نگاه کنید. نمیدونم چرا در هر حالت 1320 میشه در صورتی که قرار بود جواب 1300و1320و1340 شود.
خیر! همچین قراری نبود و رفتار تابع کاملا درسته:لبخند:
ببینید وقتی شما بازه گرد کردن رو برابر 40 قرار دادید منظور اینه که می خواید ورودی های تابع به مضارب 40 تبدیل بشن (البته غیر از اون شرایط مرزی که تکلیفش معلومه). خوب 1320 هم مضرب 40 هست، پس تمام اعدادی که فاصلشون باهاش کمتر از 20 (یعنی نصف بازه) باشه، به 1320 گرد می شن.
برای شفاف تر کردن بیاین تابع گرد کردن معمولی رو بررسی کنیم، خوب تابع Round در مورد مقادیر 5.9، 6.0 و 6.1 یه جواب میده و اون هم برابر 6ه. که کاملا هم منطقیه. اما وقتی مقادیر نزدیک به شرایط مرزی میشن ، خروجی های متفاوتی داریم، مثل 13.4، 13.5 و 13.6 که خروجی های متفاوتی داره که به ترتیب برابرن با: 13، 13.5 و 14. البته فرض کنید Round رفتاری شبیه به تابع مدنظر ما داره.
اگه می خواید اون تصمیم گیری در شرایط مرزی رو با مقادیر نزدیک به 1320 ببینید، تابع رو با همون بازه و اعداد قبل و بعد 1300 یا 1340 آزمایش کنید که مضرب 40 نیستند.
نقل قول:
توضیحی راجع به StrToIntDef
خوب توابع StrToInt و StrToFloat رو که میشناسید، برای تبدیل مقادیر رشته ای به مقادیر عددی استفاده میشن. اما اگه رشته ورودی معادل یه مقدار عددی نباشه باعث بروز خطا میشن. حالا توابع StrToIntDef و StrToFloatDef یه پارامتر Default دارن که تعیین میکنه در صورت ناممکن بود تبدیل مقدار رشته به عدد چه مقداری در خروجی قرار بگیره. در واقع به این ترتیب می تونیم از ایجاد خطا جلوگیری کنیم.
StrToIntDef('12', 2); // 12
StrToIntDef('Ali', 2); // 2
توابع دیگه ای مثل TryStrToInt و TryStrToFloat هستند که به شکل دیگه ای همین کار رو انجام میدن که در موردشون تو راهنمای دلفی می تونید بخونید. برای دیدن لیست این توابع و بقیه توابع تبدیل نوع، توی بخش Index راهنما دنبال عبارت Type conversion routines بگردید.
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
با اجازه صاحب نظران گرامی من یه سوال از آقای Gold بپرسم.
اگر گام 20 بود برای 39و 40 و 41و 59و 60و 61 چی انتظار دارید؟
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
ببینید:
اگه گام حد وسط رو 20 باشه :
39 بیشه 20
40 بیشه 40
41 بیشه 60
59 بیشه 40
60 بیشه 60
61 بیشه 80
ممنون.
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
جناب Gold اینجا یه موضوع گنگ میشه.
اگر 41 بشه 60 چطور 59 که از اون بزرگتره میشه 40؟
اون وقت تکلیف اعداد 49و 50و 51 چی میشه؟
یعنی اینکه range شما اگر یرای 60 شدن از 41 به بالا هست 59 چرا نمی شه 60؟
می تونید دقیقا مرز این range ها رو معین کنید؟
اگر بشه رو کاغذ ؛ حتما براش میشه تابعی نوشت / پیدا کرد.
لطفا range برای 0 شدن - 20 شدن و 40 شدن رو بگید.
حتما هم بهتر از بنده می دونید که range ها نباید همپوشانی داشته باشند.
باز هم از اساتید عذر می خوام
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
ممنون از شما
آفرين
سوال رو من پرسيده بودم . اما چون بي دقتي كردم. مسئله حل نشد.
جواب بنده تا حدودي همون پست دوست خوبم SAASTN بود.
سوالم رو به پيشنهاد شما بردم رو كاغذ و فهميدم كلا اشتباه مطرح كردم.
سوال اصلي به اين صورته:
تابعي بنويسيم كه بر اساس تصميم كاربر رند به بالا و پايين كنه. يعني چي:
در درجه اول اعداد خروجي جزو مضربهاب گام باشند.
مثلا اگه گام 20 بود(رند به سمت بالا)
عدد 0 تا19 بشه 20.
عدد 20 بشه 20
عدد21 تا 39 بشه 40
عدد 40 بشه 40
عدد 41 تا 59 بشه 60
به همين منوال
و اگه گام 20 بود و كاربر رند به سمت پايين رو انتخاب كرده بود
از عدد 0 تا 19 بشه 0
عدد 20 بش 20
عدد 21 تا 39 بشه 20
عدد 40 بشه 40
از عدد41 تا 59 بشه 40
عدد 60 بشه 60
از عدد 61 تا 79 بشه 60
و به همين صورت.
من يه همچين چيزي ميخواستم كه بر اثر بي دقتي من تاپيك يه مقدار منحرف شد.
از دوستان عذز ميخام و تشكر ميكنم بابت پيگيريشون.
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
سلام
برای محاسبه مقدار تقریبی یک عدد با تقریب کمتر از یک عدد مشخص از دو روش استفاده میشه:
1. روش گرد کردن که برای انجام اون از تمام چیزایی که تو پستهای بالا گفته شده، میشه استفاده کرد.
2. روش قطع کردن که فکر میکنم سوال شما تا حدود زیادی مربوط به این روش بشه. البته تا جایی که اطلاع دارم سوال شما دقیقاً با این روش منطبق نیست ولی کد زیر میتونه جوابی برای سوال شما باشه:
type
UpDown = (Down, Up);
function Taghrib(N: Longint; T: Word; Jahat: UpDown): Longint;
var
P: Longint;
begin
P := Trunc(Exp((Trunc(ln(T) / ln(10))+1) * ln(10)));
Taghrib := ((N div P) * P) + (((N mod P) div T)+Byte(Jahat)) * T;
end;
تابع بالا هر عدد داده شدهی N رو با تقریب T به روش قطع کردن در جهت Jahat، تقریب میزنه.
روش کار:
از سمت راست عدد داده شدهی N به تعداد ارقام T حذف میکنیم و بجای آن صفر قرار میدهیم.
برای اینکار ابتدا تعداد ارقام عدد T رو بدست میاریم:
Trunc(ln(T) / ln(10))+1
بعد 10 رو به توان تعداد ارقام بدست اومده میکنیم (مقدار P بدست میاد).
در انتها مقدار حذف شده از سمت راست N رو در جهت دلخواه گرد میکنیم.
توجه: عمداً از تابع Power استفاده نکردم!
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
واقعا جالب بود.
میشه بیشتر در مورده کدتون توضیح بدید؟
فقط یه مشکل داره...(البته جسارتا)
وقتی میزاریم رند بشه به سمت بالا. اگه گام رو بزاریم 10 و رند به سمت بالا باشه اگه عدد 10 رو وارد کنیم میشه 20.
در صورتی که میخواهیم بشه 10.
البته این موضوع در رند به سمت پایین درست کار میکنه.
ممنون از کمکتون.
-
توضیح کد نوشته شده در پست #22
نقل قول:
نوشته شده توسط
Gold
واقعا جالب بود.
میشه بیشتر در مورده کدتون توضیح بدید؟
فقط یه مشکل داره...(البته جسارتا)
وقتی میزاریم رند بشه به سمت بالا. اگه گام رو بزاریم 10 و رند به سمت بالا باشه اگه عدد 10 رو وارد کنیم میشه 20.
در صورتی که میخواهیم بشه 10.
البته این موضوع در رند به سمت پایین درست کار میکنه.
ممنون از کمکتون.
سلام
در مورد مشکل، حق با شماست. البته مشکل فقط برای گام 10 نیست؛ در رند به سمت بالا، اگر عدد وارد شده به عدد گام ختم بشه (مثلاً 1120 با گام 20) باز هم این مشکل پیش میاد (تو این مثال میشه 1140).
برای رفع مشکل، به نظر من یه If قبل از خط آخر اشکال کار رو برطرف میکنه:
if T = N mod P then Jahat := Down;
توجه! قسمتهای آبی رنگ توضیحات ریاضیه و ربطی به برنامه نویسی نداره. اگه حوصله ندارین نخونین.
این کد تقریباً از روش قطع کردن، برای تقریب زدن استفاده میکنه.
روش قطع کردن به این صورت هست که شما به تعداد صفرهای سمت راست گام، ارقام سمت راست عدد مورد تقریب رو صفر میکنید (مثلاً 1340 با تقریب کمتر از 100 میشه 1300). این همون رند به سمت پایین مورد بحث تاپیک هست. و البته برای رند به سمت بالا، میشه قرارداد کرد که بعد از صفر کردن یک واحد به اولین رقم غیر صفر از سمت راست اضافه بشه (مثلاً برای 1340 با تقریب کمتر از 100، اول میشه 1300 بعد 3 رو با 1 جمع میکنیم و میشه 1400).
اما این روش برای توانهای صحیح 10 با همین قراردادها جواب میده، اما برای بقیهی اعداد (مثلاً 35) باید کمی دستکاری بشه. چون ممکنه عدد داده شده اصلاً به صفر ختم نشه (همون 35) بنابراین توی این کد
اول ـ تعداد ارقارم عدد گام رو حساب میکنیم؛ برای اینکار از خواص لگاریتم نپری (همون ln) استفاده کردم. با تقسیم ln هر عدد بر ln(10) و جمع قسمت صحیح خارج قسمت این تقسیم با 1، تعداد ارقام عدد به دست میاد. نمیدونم این روش جایی ثبت شده یا نه، ولی یه روش درسته. این روش رو، من با معکوس کردن روش محاسبهی توان بدست اوردم:
a^b = e^(b*ln(a))
البته از تابع Trunc هم برای حذف قسمت اعشاری عدد بدست اومده استفاده کردم.
دوم ـ برای صفر کردن سمت راست عدد مورد تقریب به تعداد ارقام مورد نیاز، ابتدا با همین فرمول بالا، 10 رو به توان تعداد ارقام عدد گام میبریم (مثلاً برای 35، میشه 10 به توان 2 یعنی 100). بعد عدد مورد تقریب رو به اون تقسیم و ضرب میکنیم (مثلاً 1340 تقسیم بر 100 و ضرب در 100 که مساوی 1300 هست: 1300 = 100 * 100 div 1340). و در آخر هم باقیموندهی تقسیم قبل رو بر گام تقسیم و ضرب میکنیم. منتها قبل از ضرب، اگه رند کردن به سمت بالا باشه، یه واحد به خارج قسمت تقسیم دوم اضافه میکنیم. اینکار رو با عبارت Byte(Jahat)+ انجام میدم (مثلا برای 1340، باقیموندهی تقسیم اول میشه 40 و بعد 40 تقسیم بر 35 میشه 1. حالا اگه رند به سمت بالا باشه 1+1 رو در 35 ضرب میکنیم و حاصل رو با 1300 جمع میکنیم).
موفق باشید.
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
این رو تست کن Gold جان:
function F(X: real; Step: integer; UpSide: boolean): integer;
begin
result := IfThen(UpSide, Ceil(X / Step) * Step, Floor(X / Step) * Step);
end;
-
1 ضمیمه
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
این هم شاید کمکی بکنه به درک قضیه:
ضمیمه 71051
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
سلام
تابع کامپایل نمیشه . IfThen چیه؟
یه بار دیگه تابع رو بخونید.
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
سلام.
ifthen یه تابع هست در یونیت Math.
اگر شرط true باشه قسمت اول رو برمیگردونه در غیر اینصورت دومی رو.
یه ifthen دیگه هم تو StrUtils هست که خروجی اون string هست. اما خروجی این عدده.
function F(X: real; Step: integer; UpSide: boolean): integer; begin result := IfThen(UpSide, Ceil(X / Step) * Step, Floor(X / Step) * Step);end;
تست کردم مشکل نداره.
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
ممنون از همه دوستان عزیز. همگی محبت کردید.
ماشالله اینجا همه واسه خودشون ریاضی دان هستند.
تابع شما هم yousijoon عزیز جواب داد. در حد تیم ملی. اگه محبت کنید و یه توضیحی در مورد روش کار بفرمایید عالی میشه.
بازم از همه دوستان تشکر میکنم.
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
چشم:
IfThen(UpSide, Ceil(X / Step) * Step, Floor(X / Step) * Step); // tabe
اگر UpSide مقدار True داشت خروجی میشه Ceil اگر نه Floor
Ceil یعنی سقف یک عدد اعشاری به عدد صحیح بالا سرش.اگر خودش صحیح بود میشه خودش.
اگر کمترین جزء اعشاری داشت میشه عدد بعدش.
Floor هم دقیقا برعکسشه.
اما توضیح:
اگر هر عددی تقسیم به Step بشه و قسمت صحیح اون ضرب در Step بشه در حقیقت عمل قطع به Step انجام شده.
مثال:
27
/
4
=
6.75
قسمت صحیح = 6
6*4 = 24
اگر Step یک باشه همون قطع آشنا بدست میاد.
حالا یه فکری برای قسمت اعشار باید می کردیم.
خیلی ساده عدد حاصله رو اگر یکی زیاد می کردیم یا اینکه نمی کردیم هردو حالت تولید میشد.
چون Step ها هم حالت بینابینی نداشت عدد حاصله هم توش ضرب میشد.برای همین دیگه اعشارشو جدا نکردیم و با یه تیر دو نشون زدیم.
27
/
4
=
6.75
6.75 -> 7
7 * 4 = 28
6.75 -> 6
6 * 4 = 24
-
دوستان همه يه منظورو دارن ولي به روش هاي مختلف
يكي زحمت بكشه يه فايل براي دانلود برا همه بذاره،بقيه استفاده كنن و تغييرش بدن
اصل دوستان اينو مي خوان كه
هر عددي رو خواستم به هر عدد رندي تبديل كنند
مثال
1252 بشه 1260 يا 1300
16525 بشه 16530 يا 16600 يا 17000
1265347 بشه 1265350 يا 1265400 يا 1266000 يا 127000 يا 130000
و تعداد رقم هاي رند كردن دست خودشون باشه !!
يه چيزي مثل اين
Label1.Caption = Math.Round(Text1.Text, 3)
ولي برا اعداد صحيح
-
نقل قول: ساخت تابعی برای رند کردن (گرد کردن) اعداد (سفارشی)
سلام.
Pascal
function RoundToNum(X: Integer; RoundParam : Integer = 10):Integer;
begin
Result := (X div RoundParam) * RoundParam;
if (((X - Result) * 2) > RoundParam) then
Result := Result + RoundParam;
end;
C++
int RoundToNum(int X, int RoundParam)
{
int Result = int(X / RoundParam) * RoundParam;
if (((X - Result) * 2) > RoundParam)
Result += RoundParam;
return Result;
};