PDA

View Full Version : خروجی باید صفر شود؛ ولی دقیقا صفر نیست!



AtabakFathi
سه شنبه 19 بهمن 1400, 16:10 عصر
با سلام خدمت اساتید
من یه برنامه نوشتم تا نسبت های مثلثاتی رو حساب کنه.
من 90 درجه رو می زنم تا حساب کنه، ولی کسینوس اون به جای اینکه 0 بشه، یه عدد نزدیک به 0 میشه به این صورت:
0.0000000000000000616222912
(عدد تقریبیه فقط خواستم شما رو به تصوری از اون برسونم)
محض احتیاط به اکسل هم رفتم ولی اونجا هم اینطور نشون میده.
ایراد از برنامست یا کامپیوتر؟
فقط من برای فهمیدن جواب این سوال کمی عجله دارم و ممنون میشم که هر چه سریعتر جواب بدید.
عکس برنامه رو با کد های اون بخش و یه اسکرین شات از اکسل اینجا میذارم:
153684153685153686

mazoolagh
سه شنبه 19 بهمن 1400, 17:57 عصر
سلام و روز خوش
در محاسبات عددی غیر صحیح همیشه خطا داریم و بازای هر محاسبه این خطاها رو هم انباشته میشن.
وقتی شما از نوع double استفاده میکنین هر داده رو تا 15-16 رقم دقت میتونین ذخیره کنین ولی همینجور که محاسبات با اونها انجام میدین این خطاهای انباشته بتدریج دقت تعداد ارقام نتیجه رو کم میکنن و مثلا ممکنه به 12 رقم یا 10 رقم و ... برسه.
نتیجه خروجی با چند رقم کمتر از 16 نشون بدین.

AtabakFathi
سه شنبه 19 بهمن 1400, 18:52 عصر
منظورتون اینه که اون عددی که در تکست باکس ها نشون داده میشه، باید دقت کمتری داشته باشه؟
و اینکه من از گفته ی شما اینو برداشت میکنم که این موضوع (که در اکسل هم رخ داد) به نوع داده ی double مربوطه. درسته؟

mazoolagh
چهارشنبه 20 بهمن 1400, 11:28 صبح
منظورتون اینه که اون عددی که در تکست باکس ها نشون داده میشه، باید دقت کمتری داشته باشه؟
بله، بهش فرمت بدین که فرضا با 4 رقم اعشار نمایش بده.


و اینکه من از گفته ی شما اینو برداشت میکنم که این موضوع (که در اکسل هم رخ داد) به نوع داده ی double مربوطه. درسته؟
محاسبات اعشاری کلا توسط بخش floating point unit=fpu پردازنده انجام میشه مگر این که یک کتابخانه اختصاصی برای زبان/محیطی که کار میکنین وجود داشته باشه که از اون استفاده کنین.
مثلا دقت quadruple هم داریم که در بعضی نسخه های فرترن و (احتمالا زبانهای تخصصی دیگه) استفاده میشه.
همه برنامه ها در حالت عادی از fpu برای محسابات اعشاری استفاده میکنن و بنابرین نتیجه کار یکسان هست.

AtabakFathi
سه شنبه 26 بهمن 1400, 08:37 صبح
ممنون دوست عزیز
مشکل برطرف شد.
ولی یک مشکل دیگر هم هست.
اساسا تانژآنت 90 درجه باید بی نهایت بشه، ولی یه عدد دیگه به عنوان تانژانت 90 درجه نشون میده.
و همچنین تانژانت 270 هم باید بی نهایت باشه، ولی برای اون هم یه عدد دیگه نشون میده (4 برابر قبلی).

153700153701153702

mazoolagh
چهارشنبه 27 بهمن 1400, 08:59 صبح
برای نمایش مقدار بی نهایت بجای اینکه اون رو محاسبه کنین مستقیم بسازید،
به این صورت که برای زوایای مضرب 90 درجه مقادیر رو خودتون مشخص کنین.
double zero = 0;
string pos_inf = (1 / zero).ToString();
string neg_inf = (-1 / zero).ToString();

mazoolagh
چهارشنبه 27 بهمن 1400, 09:01 صبح
public trig trig_values(string degree) {
double zero = 0;
string pos_inf = (1 / zero).ToString();
string neg_inf = (-1 / zero).ToString();
decimal d = Convert.ToDecimal(degree);
decimal scale = 1;
string[] a = degree.Split('.');
if (a.Length == 2)
{
d = Convert.ToDecimal(degree.Replace(".", ""));
for (int i = 0; i < a[1].Length; i++) { scale = scale * 10; }
}


d = d % (360 * scale);
double r = (double)d * Math.PI / 180 / (double)scale;
trig x;
switch (d)
{
case 0:
{
x.sin = "0";
x.cos = "1";
x.tan = "0";
x.cot = pos_inf;
break;
}


case var v when v == 90 * scale:
{
x.sin = "1";
x.cos = "0";
x.tan = pos_inf;
x.cot = "0";
break;
}


case var v when v == 180 * scale:
{
x.sin = "0";
x.cos = "-1";
x.tan = "0";
x.cot = neg_inf;
break;
}


case var v when v == 270 * scale:
{
x.sin = "-1";
x.cos = "0";
x.tan = neg_inf;
x.cot = "0";
break;
}


default:
{
x.sin = Math.Sin(r).ToString();
x.cos = Math.Cos(r).ToString();
x.tan = Math.Tan(r).ToString();
x.cot = (1 / Math.Tan(r)).ToString();
break;
}
}
return x;
}

mazoolagh
چهارشنبه 27 بهمن 1400, 09:05 صبح
public struct trig {
public string sin;
public string cos;
public string tan;
public string cot;
}

mazoolagh
چهارشنبه 27 بهمن 1400, 09:07 صبح
private void Button1_Click(object sender, EventArgs e) {
trig x = trig_values(degree.Text.Trim());
tbsin.Text = x.sin;
tbcos.Text = x.cos;
tbtan.Text = x.tan;
tbcot.Text = x.cot;
}

mazoolagh
چهارشنبه 27 بهمن 1400, 09:14 صبح
153704
153705153706
153707153708

AtabakFathi
پنج شنبه 28 بهمن 1400, 18:51 عصر
ممنون. پس از نظر شما راه خاصی برای حل این مشکل - البته در محاسبه - نیست و باید خودم برای این موارد خاصی، مقدار بدم.

mazoolagh
دوشنبه 02 اسفند 1400, 11:38 صبح
در محاسبه حتی برای مقادیر خاص مشکلی نیست، در نمایش هست که چون شما تاکید بر شکل صحیح و دقیق مقادیر خاص دارین باید کنترل کنیم.

از طرفی چک دقیق و قطعی این مقادیر خاص هم وقتی از نوع double (کلا غیرصحیح) باشن امکانپذیر نیست، برای همین در کد پیوست مقدار درجه رو به decimal تبدیل کردم ولی بخش اعشاری اون رو منظور کردم (scale).
به این صورت میشه دقیقا با یک مقدار صحیح مقایسه کرد.