Saturday, April 14, 2007

Visual C++

بسم الله الرحمن الرحیم

به وبلاگ آموزش Visual C++ خوش آمدید. در این وبلاگ سعی شده با ارائه مثالهای کاربردی به ارتقای سطح علمی برنامه نویسان C++ کمک شود. لازم به تذکر است برای استفاده از مطالب این وبلاگ باید آشنایی قبلی با برنامه نویسی C++ و MFC داشته باشید.

توجه : چنانچه قسمتی از کد بریده شده بود اندازه متن صفحه را کوچک کنید.

1- ریاضیات و ++C

آیا عدد N جزو سری اعداد فیبوناچی است یا خیر

تعیین تعداد N باکتری تولید شده از N باکتری اولیه در N دقیقه

تبدیل رادیان به درجه ، گراد و بالعکس

توزیع دو جمله ای در آمار

تشخیص اینکه ایا عددی اعشاری هست یا خیر

محاسبه ریشه های معادله دو مجهولی با استفاده از اشاره گرها

محاسبه فاکتوریل یک عدد

محاسبه ریشه (رادیکال) یک عدد با فرجه ای غیر از ۲

کار با توابع مثلثاتی

منحنی نرمال

تشخیص اینکه آیا عددی کامل است یا خیر

محاسبه تعداد صفرها بین ممیز و اولین عدد غیر صفر در اعداد کوچکتر از یک

تشخیص کبیسه بودن سال میلادی

تشخیص اینکه ایا عددی اول است یا خیر

توزیع پواسون

محاسبه تعداد ارقام یک عدد

محاسبه لگاریتم در مبنایی غیر از ۱۰

یافتن Nامین عدد فیبوناچی

محاسبه تعداد ذره جرم معینی از یک ماده

نکته : برای استفاده از توابع ریاضی تعریف شده در Visual C++ مانند لگاریتم حتما فایل هدر #include "math.h" و در Visual C++.Net فایل #include "cmath.h" به فسمت فایل های هدردر فایل اصلی پروژه که دارای پسوند(*.CPP) می باشد، اضافه کنید.فایل اصلی پروژه فایلی است که کدهای برنامه را در آن می نویسید و به صورت (View.CPPنام برنامه یا Dlg.Cppنام برنامه) می باشد. نام CMathDlg نام فرضی است که برای پروژه انتخاب کردم.

توصیه می کنم برای اطلاع از توابع ریاضی به فایل math.h یا cmath.h مراجعه کنید.


تشخیص اینکه ایا عددی اعشاری هست یا خیر

در Visual C++ تابعی به نام modf وجود دارد که قسمت صحیح و اعشاری عدد را در صورت وجود بر می گرداند. پس برای تشخیص اعشاری بودن یا نبودن یک عدد تابعی به نام IsFloatNumber(double Number) و از نوع BOOL ایجاد و کد زیر را در آن بنویسید:

BOOL CMathDlg::IsFloatNumber(double Number)

{

BOOL bFloat=FALSE;

double FloatPart=0,IntPart=0;

FloatPart=modf(Number,&IntPart);

if(FloatPart!=0)

{

bFloat=TRUE;

}

return bFloat;

}

در کد بالا چنانچه قسمت اعشاری عدد برابر با صفر گردد تابع مقدار ۱ یعنی TRUE را بر می گرداند. همانطور که در قسمت قبل توضیح دادم متغیر IntPart مقدار قسمت صحیح عدد را در خود نگه می دارد.

توزیع دو جمله ای در آمار

در علم احتمالات ، احتمال واقع شدن دقیقا k پیروزی در n آزمایش تکراری به وسیله رابطه زیر نشان داده می شود:

P(k)=C(n,k)Pkqn-k

q احتمال شکست و برابر با q=1-P می باشد. عبارت C(n,k) ترکیب نام دارد. برای محاسبه ترکیب و توزیع دو جمله ای باید دو تابع جداگانه بنویسیم. ابتدا تابعی برای ترکیب به نام Combination(long n,long k) و از نوع long ایجاد و کد زیر را در آن تایپ می کنم:

long CMathDlg::Combination(long n,long k)

{

long r=0;

r=n-k;

return (Factorial(n))/Factorial(k)*Factorial(r);

}

تابع فاکتوریل را در قسمت فاکتوریل عدد توضیح دادم. حال برای محاسبه توزیع دو جمله ای تابعی به نام

Pk(long n,long k,double P) واز نوع double ایجاد کنید و کد زیر را در آن تایپ کنید:

double CMathDlg::Pk(long n, long k, double P)

{

double q=1-P;

return (double)Combination(n,k)*(pow(P,k))*(pow(q,(n-k)));

}

مثالی رادر این زمینه حل می کنیم.

خانواده ای دارای ۶ فرزند است. احتمال اینکه ۲ تا پسر و ۴ تا دختر باشد چقدر است.

چون احتمال پسر یا دختر بودن 1/2 است بنابراین n=6،k=2، P=1/2،q=1-P می باشد. پس اگر مقدار ها را به جای پارامتر تابع قرار دهید خواهید دید که جواب برابر با 0.234375 می باشد.

تعیین تعداد N باکتری تولید شده از N باکتری اولیه در N دقیقه

در این مثال محاسبه می کنیم که از چند باکتری بعد از مدت معینی چقدر باکتری تولید خواهد شد. برای این کار تابعی به نام

BacteriaGrowth(long nPrime, long reGenerationTime, long Period, BOOL bMinute) و از نوع double ایجاد کنید. سپس کد زیر را در آن تایپ کنید:

double CMathDlg::BacteriaGrowth(long nPrime, long reGenerationTime, long Period, BOOL bMinute)

{

long double Num=0;

if(bMinute==FALSE)

{

reGenerationTime*=60;

Period*=60;

Num=(Period*0.301+(reGenerationTime*log10(nPrime)))/reGenerationTime;

}

else if(bMinute)

{

Num=(Period*0.301+(reGenerationTime*log10(nPrime)))/reGenerationTime;

}

return (double)pow(10,Num);

}

در تابع فوق reGenerationTime به مفهوم زمان تجدید نسل می باشد. nPrime تعداد باکتری اولیه و Period مدت زمانی است که می خواهیم بدانیم بعد از این مدت چه تعداد باکتری به وجود می آید و bMinute تعیین می کند.آیا زمان برحسب دقیقه باشد یا ساعت. به عنوات مثال از ۳ سلول باکتری با زمان تجدید نسل ۱۵ دقیقه ای بعد از ۴ ساعت چه تعداد باکتری به وجود می آید. nPrime=3، reGenerationTime=15، Period=4 hours . جواب تقریبا برابر است با ۱۸۹۲۸۸ باکتری.

تبدیل رادیان به درجه ، گراد و بالعکس

برای کار با توابع مثلثاتی لازم است که گاهی رادیان به درجه یا گراد و بالعکس تبدیل شود. برای منظور تابعی به نام GRD(double Number,LPCTSTR Unit) و از نوع double ایجاد و کد زیر را در آن بنویسید:

double CMathDlg::GDR(double Number, LPCTSTR Unit)

{

double Num=0;

if(Unit==_T("D to R"))

{

Num=Number*PI/180;

}

else if(Unit==_T("R to D"))

{

Num=Number*180/PI;

}

else if(Unit==_T("G to R"))

{

Num=Number*PI/200;

}

else if(Unit==_T("G to D"))

{

Num=Number*180/200;

}

else if(Unit==_T("R to G"))

{

Num=Number*200/PI;

}

else if(Unit==_T("D to G"))

{

Num=Number*200/180;

}

return (double)Num;

}

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

آیا عدد N جزو سری اعداد فیبوناچی است یا خیر

برای تشخیص اینکه آیا عدد N جزو سری اعداد فیبوناچی است یا نه باید از فرمول زیر استفاده کنیم:

X=5N2-4 Or X=5N2+4

که اگر X به دست آمده در هریک از معادلات فوق دارای جذر کامل باشد(یعنی اعشاری نباشد مانند جذر ۱۶) آن عدد جزو سری اعداد فیبوناچی است. مثلا عدد ۲ را در نظر بگیرید چنانچه این عدد را به جای N قرار دهیم جواب برابر ۱۶ می شود و چون ۱۶ دارای جذر کامل می باشد (۴ ) پس عدد ۲ جزو سری اعداد فیبوناچی است ولی اگر X به دست آمده از هردو معادله دارای جذر کامل نباشد آن عدد جزو سری اعداد فیبوناچی نیست.

اکنون تابعی می نویسیم که این کار را انجام دهد. برای این منظور تابعی به نام IsFibonacci(long Number) و از نوع BOOL ایجاد و کد زیر را در آن بنویسید:

BOOL CMathDlg::IsFibonacci(long Number)

{

BOOL bFibonacci=FALSE;

double X=0,X2=0;

double y=0,n=0,n2=0,y2=0;

X=sqrt((5*Number*Number)-4);

X2=sqrt((5*Number*Number)+4);

y=modf(X,&n);

y2=modf(X2,&n2);

if(y==0||y2==0)

{

bFibonacci=TRUE;

}

return (BOOL) bFibonacci;

}

باز در تابع فوق از تابع modf که قسمت صحیح و اعشاری را بر می گرداند استفاده کردیم. چنانچه متغیر y يا y2 برابر صفر شد یعنی عدد ما جذر کامل داشته پس عدد مورد نظر جزو سری اعداد فیبوناچی می باشد.

Visual C++

منحنی نرمال

در علم آمار و در مبحث احتمال از منحنی به نام منحنی نرمال یا منحنی گوس استفاده می کنند.

فرمول منحنی نرمال به صورت زیر می باشد:

Y=N/σ√2π*e-0.5(X-μ/σ)( X-μ/σ)

که در آین فرمول π برابر با 3.14159265 و e عدد نپر، μ میانگین و σ انحراف استاندارد می باشد. برای رسم منحنی باید مقادیر مختلف X را جایگزین کرد تا Y به دست آید. اکنون تابعی می نویسیم که مقدار Y را محاسبه کند. ابتدا تابعی به نام NormalCurve(long N,long X,double Mean,double SD)

و از نوع double تعریف کنید. سپس قطعه کد زیر را در آن بنویسید:

double CMathDlg::NormalCurve(long N,long X,double Mean,double SD)

{

return (N/SD*sqrt(2*PI))*pow(NAPIER,-0.5*(pow((X-Mean)/SD,2)));

}

همانطور که در کد فوق مشاهده می کنید ابتدا از تابعی به نام sqrt استفاده کردیم این تابع جذر عدد را بر می گرداند و از توابع ریاضی Visual C++ است. ماکروی PI ماکروی تععین شده توسط خودمان است که عدد پی را در خود نگه می دارد. همچنین ماکروی NAPIER نگدارنده عدد نپر است. برای تعریف این ماکروها در ابتدای فایل اصلی برنامه و بعد از دستورات پیش پردازنده دو دستور زیر را تایپ کنید.

#define PI 3.1415926535897932384626433832795

#define NAPIER 2.71821828

تابع pow نیز قبلا مورد بحث قرار گرفته است. دقت کنید عدد ۰.5 همان جواب کسر ۲/۱ می باشد.

کار با توابع مثلثاتی

توابع مثلثاتی یکی از مهمترین بخشهای ریاضیات می باشد کاربرد فراوانی در علوم مهندسی، فیزیک و شیمی دارد. در این بخش نحوه چگونگی استفاده از بعضی توابع مثلثاتی را توضیح می دهیم. تابعی که در مورد آن صحبت می کنیم تابع sin می باشد. این تابع یکی از توابع تعریف شده در فایل هدر math می باشد. این تابع اندازه رادیان زاویه ای را بر می گرداند. برای اینکه این تابع اندازه زاویه را به درجه محاسبه کند باید رادیان را به درجه تبدیل کنیم. برای شروع کار تابعی به نام Sin(double Number,double Pow) و از نوع double در پروژه تعریف کنید. دقت کنید حتما حرف اول تابع با حرف بزرگ نوشته شود. سپس قطعه کد زیر را در آن بنویسید:

double CMathDlg::Sin(double Number,double Pow)

{

return (double)pow(sin(Number*PI/180),Pow);

}

همانطور که می بینید در این تابع از ماکروی PI که در قسمت قبل تعریف آن را توضیح دادیم و عدد پی را در خود نگه می دارد، استفاده کردیم. ما در این تابع پارامتر توان را اضافه کردیم چون گاهی پیش می آید که لازم است توان یک زاویه مثلثاتی حساب شود. برای تبدیل رادیان به درجه از فرمول Number*PI/180 استفاده کردیم. اکنون اگر عدد 30 را در تابعی که تعریف کردیم قرار دهید خواهید دید که جواب برابر با 0.5 است.

*تمرین : Sin345 را حساب کنید و ببینید جواب چقدر می شود. عدد 3 را در پارامتر Pow قرار دهید.

همین کار را برای توابع cos،tanانجام دهید.

برای تابع cotg که در فایل math تعریف نشده است تابعی بنویسید. (راهنمایی: اندازه کتانژانت از تقسیم کسینوس بر سینوس به دست می آید)

نکته: توابه مثلثاتی که به حرف h ختم می شوند توابع مثلثاتی هیپربولیک هستند.

محاسبه ریشه (رادیکال) یک عدد با فرجه ای غیر از ۲

همانطور که می دانید برای به دست آوردن ریشه یک عدد باید از آن عدد جذر گرفت. بعضی اعداد دارای جذر کامل هستند به این معنی که جذر آنها یک عدد صحیح و بدون اعشار است. مانند ۱۶ که جذر آن ۴ می باشد. در برنامه زیر تابعی می نویسیم که رادیکال عددی را با فرجه ای غیر از ۲ محاسبه کند. پس تابعی به نام RootN(double Number,double root,double Pow) واز نوع double ایجاد کنید. سپس قطعه کد زیر را در آن بنویسید:

double CMathDlg::RootN(double Number,double root,double Pow)

{

return pow(Number,(Pow/root));

}

در تابع فوق root ریشه Nام و Pow توان عدد زیر رادیکال است. در واقع ریشه عدد توان عدد تقسیم بر فرجه رادیکال می باشد. به عنوان مثال جذر ۹ یعنی ۹ به توان 0.5 یا همان ۱/۲.

۱-12 محاسبه فاکتوریل یک عدد

فاکتوریل یک عدد مانند ۵ به صورت زیر محاسبه می شود:5!=1*2*3*4*5=120

اکنون تابعی می نویسیم که فاکتوریل عدد را محاسبه کند. پس تابعی به نام Factorial(long Number) و از نوع double در پروژه ایجاد کنید. سپس قطعه کد زیر را در آن بنویسید:

double CMathDlg::Factorial(long Number)

{

if(Number<=1)

return 1;

else return (__int64)Number*Factorial(Number-1);

}

در کد تابع از مکانیسم تابع بازگشتی استفاده کردیم یعنی تابعی در داخل خودش،خودش رافراخوانی می کند.

۱-13 محاسبه ریشه های معادله دو مجهولی با استفاده از اشاره گرها

در این قصد دارم با یک مثال کاربردی روش استفاده از اشاره گرها را آموزش دهم. معادله دو مجهولی به صورت زیر است:

ax2+bx+c=0

اکنون تابعی به نام QuadraticEquation(double a,double b,double c,double * X1,double* X2)

و از نوع void ایجاد کنید. سپس قطعه کد زیر را در آن بنویسید:

void CMathDlg::QuadraticEquation(double a,double b,double c,double* X1,double* X2)

{

double x=0;

double s=pow(b,2);

double Delta=sqrt((s-4*a*c));

*X1=(-(b)+Delta)/(2*a);

*X2=(-(b)-Delta)/(2*a);

}

حالا دو کنترل کادر ویرایش و یک کنترل دکمه برروی کادر محاوره ایجاد کنید. دو متغیر به نامهای m_ed1 و m_ed2 از نوع double به ترتیب به کنترلهای کادر ویرایش اول و دوم تخصیص دهید. سپس برروی کنترل دوبار کلیک کنید و قطعه کد زیر را در آن بنویسید:

void CMathDlg::QEquation()//Function for Button Control

{

double x1=0,x2=0;

QuadraticEquation(2,-16,14,&x1,&x2);

m_ed1=x1;

m_ed2=x2;

UpdateData(0);

}

اکنون برنامه را اجرا کنید. برروی دکمه کلیک کنید تا ریشه های معادله در کادرهای ویرایش نمایش داده شوند. ریشه ها عبارتند از ۱ و ۷.

*نکته : اگر معادله ای ریشه نداشته باشد عبارت -1.#IND نمایش داده می شود.

همانطور که می دانید نوع void هیچ مقداری را بر نمی گرداند اما ما با استفاده از اشاره گرها مقدار X1 و X2 را به متغیرهای x1 و x2 نسبت دادیم و سپس ما این متغیرها را به متغیرهای کادر ویرایش نسبت دادیم.

تمرین : مانند این مثال را برای قضیه فیثاغورث و زمان انجام دهید.

Visual C++

محاسبه لگاریتم در مبنایی غیر از ۱۰

در برنامه زیر می خواهیم لگاریتم عدد را در مبنایی غیر از مبنای ۱۰ محاسبه کنیم. در ریاضیات برای محاسبه لگاریتم در مینایی غیر از ۱۰ باید لگاریتم عدد و مبنا به صورت جداگانه محاسبه و سپس بر هم تقسیم کنیم. حال برنامه ای می نویسیم که این کار را انجام دهد. تابعی به نام

Log(double Number, double Base,double NumberPow,double BasePow) و از نوع double به پروژه اضافه کنید. دقت کنید حتما حرف اول تابع برای جلوگیری از تداخل با تابع اصلی Visual C++ به صورت بزرگ نوشته شود. سپس قطعه کد زیر را در آن تایپ کنید:

double CMathDlg::Log(double Number,double Base,double NumberPow,double BasePow)

{

if(Number>0&&Base>1)

{

return (NumberPow*(log10l(Number)))/(BasePow*(log10l(Base)));

}

این تابع لگاریتم هر عدد از نوع double را در هر مبنایی برمی گرداند. NumberPow توان عدد و BasePow توان پایه می باشد.

محاسبه تعداد ارقام یک عدد

گاهی لازم است تا تعداد ارقام یک عدد را بدانیم مثلا گاهی پیش می آید تا برای تبدیل یک عدد به رشته تعداد ارقام یک عدد را بدانیم. در ریاضیات برای تعیین تعداد ارقام یک عدد از لگاریتم آن عدد استفاده می کنند. بدین منظور یک واحد به قسمت عدد صحیح لگاریتم اضافه می کنند. مثال زیر این کار را نشان می دهد. برای این منظور تابعی به نام DigitOfNumber(double Number) و از نوع بازگشتی long ایجاد کنید. سپس قطعه کد زیر را در بدنه تابع تایپ کنید:

long CMathDlg::DigitOfNumber(double Number)

{

long m_Digit=0;

if(Number<0)

{

Number*=-1;

}

if(Number>1 || Number!=0)

{

m_Digit=log10(Number);

m_Digit++;

}

return (long)m_Digit;

}

در ابتدای تابع متغیری از نوع long برای نگه داری تعداد ارقام عدد تعریف شده است. دستور شرطی اول تعیین می کند که ایا عدد وارد شده مثبت است یا منفی. از آنجایی که اعداد منفی لگاریتم ندارند بنابراین چنانچه عدد منفی باشد با استفاده از عملگر انتساب مرکب (*=) عدد را مثبت می کنیم. دستور شرطی دوم تعیین می کند اگر عدد وارد شده بزرگتر از یک باشد یا متساوی با صفرنباشد مقدار لگاریتم را در متغیر m_Digit قرار می دهد. همانطور که مشاهده می کنید تابع log10 مقداری از نوع double را برمی گرداند اما متغیر ما از نوع long است این کار سبب می شود تا فقط ارقام صحیح عدد به متغیر انتقال یابد و در آخر یک واحد به متغیر اضافه می کنیم. به عنوان مثال عدد23را در نظر بگیرید. لگاریتم این عدد حدودا برابر با ۱.3۶۱۷۲۷۸۳۶۰است که با اجرای تابع یک واحد به عدد قسمت صحیح جواب (۱) اضافه می شود و عدد ۲ که نشان دهنده تعداد ارقام عدد است بر می گرداند.

تذکر: چنانچه عدد اعشاری باشد فقط تعداد ارقام قسمت صحیح عدد را بر می گرداند.

به عنوان تمرین ببینید که عدد 23e+20 چند رقم است؟

توزیع پواسون

(Poisson Distribution)

در مبحث احتمالات در علم آمار برای احتمال رخداد موفقیت از توزیع پواسون استفاده می کنیم.

فرمول توزیع پواسون به صورت زیر است:

P(X)=eλX/X!

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

به همین منظور در پروژه تابعی به نام Poisson(long X,long n,double p) و از نوع double ایجاد کنید. سپس قطعه کد زیر رادر آن بنویسید:

double CMathDlg::Poisson(long X,long n,double p)

{

return powl(NAPIER,(p*n))*powl((p*n),X)/(Factorial(X));

}

همچنین در ابتدای فایل اصلی برنامه و بعد از دستورات پیش پردازنده ماکروی NAPIER را به صورت زیر تعریف کنید:

#define NAPIER 2.71821828

در فرمول پواسون حرف (e) مخفف نپر و نشان دهنده عدد نپر می باشد. در فرمول فوق از ماکروی NAPIER استفاده کردیم. همان طور که می دانید ماکروها نوعی از ثوابت هستند که مقدار آنها در طول برنامه تغییر نمی کند و مقدار آنها جایگزین نام ماکرو می شود و چنانچه بخواهید مقدار آنها را تغییر دهید با خطای کامپایلر مواجه می شوید. همچنین از تابع از پیش تعیین شده powl استفاده کردیم که توان یک عدد را محاسبه می کند. دو نوع تابع توان داریم (pow و powl). نوعی که مانند مثال فوق به حرف انگلیسی l ختم می شود و به مفهوم آن است که تابع فوق یک عدد از نوع long double را قبول می کند و عددی از نوع long double بر می گرداند. و نوع دیگر یک عدد از نوع double قبول و عددی از نوع double بر می گرداند.

اکنون مثالی مطرح می کنیم تا با کاربرد تابع آشنا شوید.

* در یک ازمایش فضایی احتمال موفقیت هر بار آزمایش 0.005 است، اگر این ازمایش را ۱۴۰۰ بار تکرار کنیم، احتمال اینکه تعداد موفقیت ۲ باشد چقدر است.

در اینجا ۱۴۰۰=n ، 0.005=p و ۲=X می باشد. در ضمن لازم به ذکر است که λ از ضرب n و p به دست می آید که ما در تعریف تابع n و p را قرار دادیم. تابع Factorial برای محاسبه فاکتوریل عدد به کار می رود که ما خودمان آن راایجاد کردیم. برای دیدن دستورات تابع فوق به قسمت فاکتوریل مراجعه کنید. اعداد را جایگزین پارامترهای تابع قرار دهید و نتیجه را ببینید. (جواب = 0.0223)

تشخیص اینکه ایا عددی اول است یا خیر

در ریاضیات به اعدادی عدد اول اطلاق می شود که بر هیچ عددی غیر از خودشان و ۱ بخشپذیر نباشند. حال تابعی می نویسیم که تشخیص دهد ایا عدد مورد نظر اول است یا خیر. به همین منظور تابعی به نام IsPrime(long Number) و از نوع BOOL ایجاد و کد زیر را در آن تایپ کنید:

BOOL CMathDlg::IsPrime(long Number)

{

BOOL bPrime=FALSE;

if (number%2!=0&&amp;amp;amp;amp; Number%3!=0&&Number%4!=0&&Number%5!=0&&Number%6!=0&&Number%7!=0 &&Number%8!=0&&Number%9!=0)

{

bPrime=TRUE;

}

if(Number==2 || Number==3||Number==5||Number==7)

{

bPrime=TRUE;

}

return bPrime;

}

در تابع فوق از ساده ترین راه برای تشخیص عدد اول استفاده کردیم. با توجه به اینکه اعداد ۲،۳،۵،۷ جزو اعداد اول هستند و در دستور شرطی اول تابع صدق نمی کنند لذا به طور جداگانه آنها را بررسی کردیم. اعداد مختلفی را آزمایش کنید تا نتیجه را ببینید. نتیجه به صورت ۰ یا ۱ نمایش داده می شود که ۱ نشان دهنده TRUE می باشد.

تشخیص کبیسه بودن سال میلادی

برای تشخیص کبیسه بودن یا نبودن سال میلادی از ۲ را استفاده می کنیم. اگر سال میلادی قرن باشد مانند ۱۹۰۰ یا ۲۰۰۰ چنانچه این عدد بر ۴۰۰ بخشپذیر باشد آن سال کبیسه است و اگر سال غیر قرن باشد مانند ۲۰۰۷ یا ۲۰۰۱ اگر این عدد بر ۴ بخشپذیر باشد آن سال کبیسه (Leap Year) می باشد. اکنون تابعی می نویسیم تا این کار را انجام دهد. تابعی به نام IsLeapYear(int Year) و از نوع BOOL در پروژه ایجاد و کد زیر را در آن تایپ کنید:

BOOL CMathDlg::IsLeapYear(int Year)

{

BOOL bLeap=FALSE;

if((Year%100==0 &&amp;amp;amp;amp; Year%400==0)||(Year%100!=0&&Year%4==0))

{

bLeap=TRUE;

}

return bLeap;

}

در تابع فوق چک کردیم که اگر بر ۱۰۰(یعنی یال میلادی شروع قرن است) و ۴۰۰ بخشپذیر شد سال کبیسه است ولی چنانچه قرن نبود اگر بر ۴ بخشپذیر شد سال کبیسه است. به عنوان مثال سال ۱۹۰۰ کبیسه نیست اما سال ۲۰۰۰ کبیسه است.

محاسبه تعداد صفرها بین ممیز و اولین عدد غیر صفر در اعداد کوچکتر از یک

گاهی لازم است تا صفرهای بین ممیز و اولین عدد غیر صفر را محاسبه کنیم مانند تبدیل یک عدد کوچکتر از یک به رشته. برای محاسبه تعداد صفرهای بین ممیز و اولین عدد غیر صفر از لگاریتم عدد استفاده می کنیم. همانطور که می دانیم لگاریتم اعداد کوچکتر از یک منفی می باشد و عدد صحیح جواب لگاریتم نشان دهنده تعداد صفرها می باشد مثلا لگاریتم عدد 0.003 حدودا برابر با 2.522878745- است که عدد 2 نشان می دهد بین ممیز و اولین عدد ۲ صف ر قرار دارد. برای انجام این کار تابعی به نام DigitOfZero(double Number) واز نوع long ایجاد و کد زیر را در آن تایپ کنید:

long CMathDlg::DigitOfZero(double Number)

{

long m_Digit=0;

if(Number<0)

{

Number*=-1;

}

if(Number<1)

{

m_Digit=log10(Number);

m_Digit*=-1;

}

return (long)m_Digit;

}

در تابع فوق ابتدا چک می کنیم اگر عدد کوچکتر از یک شد در منفی ضرب شود چون اعداد منفی لگاریتم ندارند. سپس با استفاده از تابع لگاریتم لگاریتم عدد محاسبه و قسمت صحیح جواب در متغیر m_Digit قرار می گیرد. چون جواب منفی است بنابراین متغیر مذکور را در منفی ضرب کرده ایم. و در آخر تابع مقدار متغیر مذکور را از نوع long بر می گرداند.

تشخیص اینکه آیا عددی کامل است یا خیر

عدد کامل به عددی گویند که مجموع مقسوم علیه های آن عدد به جز خودش برابر با خود عدد گردد. مثلا عدد 6 عدد کامل است زیرا مجموع اعداد ۱و۲و۳ که ۶ بر آنها بخشپذیر است برابر با ۶ می باشد. اکنون تابعی می نویسیم که تشخیص دهد ایا عددی کامل است یا خیر. تابعی به نام IsWholeNumber(double Number) و از نوع BOOL در پروژه تشکیل دهید. سپس قطعه کد زیر را در آن تایپ کنید:

BOOL CMathDlg::IsWholeNumber(double Number)

{

if(Number<0)

{

Number*=-1

}

double Num=0;

double sum=0;

double T=0;

double Numt=Number;

BOOL WholeNum=FALSE;

double n,y,x=Number;

y=modf(x,&n);

if(y==0)

{

for(Num=1;Num<Numt;Num++)

{

if(fmod(Numt,Num)==0)

{

sum+=Num;

}

}

}

if(sum==Number)

{

WholeNum=TRUE;

{

if(Number==0)

WholeNumber=FALSE;

}

return(BOOL) WholeNum;

}

دستورات اول تابع مشخص هستند. در خط ۱۲ ما از تابعی به نام modf استفاده کردیم. علت این است که چون این تابع را فقط برای اعداد صحیح استفاده می کنیم لذا در دستور شرطی بعد چنانچه مقدار y برابر با صفر شود دستورات تکرار اجرا می شود. متغیر y مقدار اعشاری عدد و متغیر n مقدار صحیح عدد را در خود نگه می دارد. شاید بپرسید اصلا چرا از تابع modf استفاده کردیم. به خاطر اینکه پارامتر Number را از نوع double تعریف کردیم (برای اینکه بتوانیم اعداد تا 10e+308را محاسبه کنیم) و نوع double می تواند شامل اعداد اعشاری نیز باشد برای همین از تابع فوق استفاده کردیم تا تشخیص دهیم عدد وارد شده صحیح است یا اعشاری. مثلا عدد 10e+200 یک عدد صحیح است. نکته دیگر استفاده از تایع fmod است. چون برای تعیین باقیمانده اعداد از نوع double نمی توانیم از عملگر % استفاده کنیم باید از تابع fmod استفاده کنیم تا باقیمانده دو عدد برگردانده شود و اگر عدد مورد نظر بر اعداد حلقه تکرار بخشپذیر باشد(یعنی باقیمانده صفر شود) آن عدد جزو مقسوم علیه های عدد به شمار می آید و در نهایت اگر مجموع مقسوم علیه های عدد با خود عدد برابر شد تابع مقدار TRUE را بر می گرداند.

*تمرین: برای تابع تشخیص اعداد اول که در قسمت قبل توضیح دادم همانند تابع فوق از توابع modf و fmod استفاده کنید.