PDA

View Full Version : sin و cos



mg_mahyar
دوشنبه 28 اردیبهشت 1388, 23:33 عصر
سلام من میخوام از سینوس و کسینوس استفاده کنم ارور میگیره ازم.

ارورشم نمیتونم رفع کنم.
حالا نمیشه یه کاری کرد خود سینوس و کسینوس رو چیداه سازی کرد و سراغ math.h یا cmath نرفت؟

اصلا بدون اونا میخوام سینوس و کسینوسو به کار ببرم کسی بلده؟

MSJazayeri
سه شنبه 29 اردیبهشت 1388, 00:10 صبح
شما نگفتید چه ارروری میده.ولی فکر کنم اگر اینطوری بنویسید درست بشه:

a = sin((float)b)
c = cos((float)d)
علت این هم اینست که این توابع برای int تعریف نشده اند.
در مورد عدم استفاده از این هدر ها هم می توانید از سورس کامپایلر هایی مثل gcc استفاده کنید.:متفکر:

mg_mahyar
سه شنبه 29 اردیبهشت 1388, 16:27 عصر
نه مظلبت درسته من دابل تعریف کردم

A_Salimi
سه شنبه 29 اردیبهشت 1388, 18:00 عصر
خوب لابد math.h رو include نکردی.

ضمنا یادت باشه ورودی این توابع از نوع رادیان هستند و برای تبدیل به درجه باید در 3.14/180 ضرب شوند.

mg_mahyar
سه شنبه 29 اردیبهشت 1388, 18:42 عصر
خوب لابد math.h رو include نکردی.

ضمنا یادت باشه ورودی این توابع از نوع رادیان هستند و برای تبدیل به درجه باید در 3.14/180 ضرب شوند.


ای بابا
من میگم توابع سینوس و کسینوس چطوریه.
http://barnamenevis.org/forum/showthread.php?t=158636&page=2

اینجا پرسیدم. مشکل من با هدر فایل نیست. مشک با تابع هم نیست.
همه پیز تا وقتی هدر فایل math.h رو اضافه نکردم درسته.
وقتی اضافه میکنم. بهم ارور میده.
از خود ایم هدر فایلم ارور نمیده از توبعی که دارم خطا میگیره. همین توابع تا قبل از اضافه کردن هدر فایل درست کار میکردن. ولی بعدش نه.
اگرم این هدر فایلو ادد نکنم نمیتونم از سینوس یا کسینوس استفاده کنم.
برای ترسیم بیضی به سینوس کسینوس نیاز دارم.


نتیجه اخلاقی . اگر نحوه پیاده سازی سینوس و کسینوس رو بدون هدر فایل math.h یا cmath بلدید بگید.

mabbaszadegan
سه شنبه 29 اردیبهشت 1388, 21:48 عصر
خوب از بسط مک لورن استفاده کن!!!!

mg_mahyar
سه شنبه 29 اردیبهشت 1388, 22:41 عصر
خوب از بسط مک لورن استفاده کن!!!!
ایول بابا کارت حرف نداره.
:متفکر:

pswin.pooya
چهارشنبه 30 اردیبهشت 1388, 00:59 صبح
من چک کردم از متغییرهایی به اسم x0,x1,y0,y1 استفاده نکنی مشکل حل میشه.

Saeed_m_Farid
چهارشنبه 30 اردیبهشت 1388, 02:16 صبح
ایول بابا کارت حرف نداره. :متفکر:

نتیجه اخلاقی . اگر نحوه پیاده سازی سینوس و کسینوس رو بدون هدر فایل math.h یا cmath بلدید بگید.
با سلام
دوست عزيز اين لحن صحبت تو تمام تاپيكهاي شما ديده ميشه، حتي آقا نيما مدير بخش كه صرفا قصد راهنمايي شما رو داشتن هم همين تكه هاي گوشنواز رو دريافت كردن! لطف كنيد با دوستاني كه فقط قصد كمك به شما رو دارن يكمي بهتر صحبت كنيد. (اگه عرض بنده هم باعث دريافت پست نصيحت نكن و موعظه و ... نشه)

به هرصورت mabbaszadegan درست ميگن و راحت ترين راه پياده سازي سينوس و كسينوس همين بسط مك لورن هست، ولي راههاي ديگه اي هم مثل توابع نپري و استفاده از نسخه بهينه شده اسمبلي SIMD و يا كلاسهاي Template‌ كه نمونه هاي زيادي از اونها موجود هست (ضميمه شده)، وجود دارن.
واسه بسط مك لورن شما بايد دو تا تابع يكي واسه به توان رسوندن و يكي هم واسه فاكتوريل بنويسين (دروس اول راهنمايي و يه حلقه ساده واسه هركدوم) و با توجه به فرمولهاي ساده كه در شكلها آورده شده يه تابع معمولي (و نه كامل!) پياده سازي كنيد. مثلا واسه سينوس داريم :
x - 1/6 x^3 + 1/120 x^5 - 1/5040 x^7 + ... و همونطوركه ميدونيد :
cos(x) = sin(x + pi/2) ؛ درضمن يه ثابت هم واسه عدد پي تا يه حد معقول تعريف مي كنيد :
const float PI = 3.14159265358979323846264338327950288f; و ...
يه كلاس Template واسه اينكار پياده سازي كنيد، كه توضيح كاملش رو اينجا نميشه آورد؛ يه نمونه برنامه كنسول واسه پياده سازي سينوس با اين روش رو تو سايت devmaster (http://www.devmaster.net/forums/showthread.php?t=5784)اينطوري آوردن، كه شايد بتونه يه ديد از اين نوع پياده سازي به شما بده :

#include <iostream>

#include <cstdlib>
#include <ctime>
#include <cmath>


const float PI = 3.14159265358979323846264338327950288f;
const float PI2 = 6.28318530717958647692528676655900577f;
const float PID2 = 1.57079632679489661923132169163975144f;
const float PI_SQR = 9.86960440108935861883449099987615114f;template <typename T, bool accurate>
T FastSin(const T& theta)
{
const T B = 4 / PI;
const T C = -4 / PI_SQR;


T y = B * theta + C * theta * abs(theta);


if (accurate)
{
// const float Q = 0.775;
const T P = 0.225;


y = P * (y * abs(y) - y) + y; // Q * y + P * y * abs(y)
}


return y;
}


template <typename T>
T randf()
{
int randi = rand();


return (T)(((double)(randi % RAND_MAX))/((double)RAND_MAX));
}


void CheckAccuracy()
{
const size_t checks = 10000;
typedef double real;


std::cout << "Checking accuracy randomly." << std::endl;
srand((unsigned)std::time(0));


real Sin[checks], fastSin[checks], fastAccurSin[checks];
for (int i = 0; i < checks; i++)
{
real randFloat = randf<real>();
Sin[i] = sin(randFloat);
fastSin[i] = FastSin<real, false>(randFloat);
fastAccurSin[i] = FastSin<real, true>(randFloat);
}


real SinToFastSinAccurs[checks], SinToFastAccurSinAccurs[checks];
for (int i = 0; i < checks; i++)
{
// (measured - accurate)/accurate
SinToFastSinAccurs[i] = (fastSin[i] - Sin[i])/Sin[i];
SinToFastAccurSinAccurs[i] = (fastAccurSin[i] - Sin[i])/Sin[i];
}


real FinalSinToFastSin = ((real)0), FinalSinToFastAccurSin = ((real)0);
for (int i = 0; i < checks; i++)
{
FinalSinToFastSin += SinToFastSinAccurs[i];
FinalSinToFastAccurSin += SinToFastAccurSinAccurs[i];
}
FinalSinToFastSin /= (((real)checks) / ((real)100.0));
FinalSinToFastAccurSin /= (((real)checks) / ((real)100.0));


std::cout << "FinalSinToFastSin %: " << FinalSinToFastSin << "\nFinalSinToFastAccurSin %: " << FinalSinToFastAccurSin << std::endl;
}


int main()
{
CheckAccuracy();
system("Pause");
return 0;
}

از توابع اسمبلي سازگار با x86 واسه اينكار استفاده كنيد كه خيلي هم سريع هستن، واسه نمونه به كد زير مراجعه كنيد :

// cos(x) = sin(x + pi/2)

addps xmm0, PI_2
movaps xmm1, xmm0
cmpnltps xmm1, PI
andps xmm1, PIx2
subps xmm0, xmm1


// Parabola
movaps xmm1, xmm0
andps xmm1, abs
mulps xmm1, xmm0
mulps xmm0, B
mulps xmm1, C
addps xmm0, xmm1


// Extra precision
movaps xmm1, xmm0
andps xmm1, abs
mulps xmm1, xmm0
subps xmm1, xmm0
mulps xmm1, P
addps xmm0, xmm1

پ.ن. : تو كد فايل ضميمه، پس از اضافه نمودن تابع cpp به پروژتون و تعريف يه instance از كلاس از توابع QuickSin و QuickCos و يا QuickSinCos با دادن پارامتر ارجاعي استفاده كنيد. و يا مستقيما از متغير سراسريgQuickTrigInitialize استفاده كنيد...


موفق باشيد.

Saeed_m_Farid
چهارشنبه 30 اردیبهشت 1388, 02:34 صبح
البته يه موضوع يادم رفت بگم : استفاده از بسط مك لارن يا تايلور سرعت تابع رو پايين مياره و با توجه به اينكه شما تو OpenGL نميتونين اين موضوع رو ناديده بگيرين، اين روش پيشنهاد نميشه!
يه راه حل ديگه هم استفاده از جدول look-up واسه اينكار هست. واسه نمونه توابع زير از dreamincode (http://www.dreamincode.net/forums/showtopic55395.htm) از اين روش استفاده كردن :
#define quarter_table_size (int)(3.14159 / 0.0002)

struct value_item
{
bool is_valid;
double result;
}sin_table[quarter_table_size],cos_table[quarter_table_size];



double static_sin(double v)
{
int k;
double mul = 1.0;

k = (int)(v * 10000) % (quarter_table_size * 4);
if(k>0){

if(k >= quarter_table_size && k < quarter_table_size * 2)
k = (quarter_table_size * 2) - k;
else if(k >= quarter_table_size * 2 && k < quarter_table_size * 3)
{
k = k - (quarter_table_size * 2);
mul = -1.0;
}
else if(k >= quarter_table_size * 3)
{
k = (quarter_table_size * 4) - k;
mul = -1.0;
}
return sin_table[k]* mul;
}

else
{
k=-k;
if(k >= quarter_table_size && k < quarter_table_size * 2)
k = (quarter_table_size * 2) - k;
else if(k >= quarter_table_size * 2 && k < quarter_table_size * 3)
{
k = k - (quarter_table_size * 2);
mul = -1.0;
}
else if(k >= quarter_table_size * 3)
{
k = (quarter_table_size * 4) - k;
mul = -1.0;
}
return -1*sin_table[k]* mul;
}

}

double static_cos(double v)
{
if(v<0)
v=-v;
return static_sin(v + (PI / 2.0));
}

mg_mahyar
چهارشنبه 30 اردیبهشت 1388, 15:30 عصر
اقا درست میگی شاید لحن من بده.
ولی باور کن بی منظورم
از همه معذرت میخوام.
ولی وقتی کسی جواب بی مورد بهم میده واقعا حالم گرفته میشه. اخه من میپرسم sin و کسینوس رو چچطور بنویسم بهم میگن متغییر اینت تعریف نکن.
بهم میگن هدر فایلو درست کن.
اینا واقعا جواب منه؟

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

بسط مکلورن رو بلدم ولی راه دومت رو بلد نبودم ممنون. خیلی گلی