PDA

Просмотр полной версии : sin в C++



un4-funeral
24.04.2008, 01:48
вот интересное дело...
если угол принадлежит от 0 до 90 градусов, то норм считает
если вводить 180 градусов, то выдаёт 1,22460635382238E-16

ну да...степень -16..то есть, если округлить, то 0
но по сути, при 180 градусах ровно 0 получится должен

От чего эта погрешность получается ?

BBB
24.04.2008, 09:52
un4-funeral,
вообще-то, любопытно, как это вы считаете синут от 180 градусов, когда значение параметра этой функции должно указываться в радианах.

Если же вы делаете (как и должно быть) преобразование 180 градусов -> радианы, то вот вам, пожалуйста, и погрешность появляется. При умножении на иррациональное число "пи".

olympian
24.04.2008, 09:54
мм..Возможно то, что sin() в С++ (стандартный из math.h) - считает не от градусов, а от радиан.
И для того требуется делить на 180 и умножить на PI.
Но ведь PI - бесконечная десят. дробя=> целиком ее ввести нельзя.
sin(PI) = 0;
но у нас sin(a) : a->PI. оно близко по значению, но всеже не равно..
Возможен такой вариант.

somewhere
24.04.2008, 14:32
Во многих библиотеках очень любят задавать число Пи фиксированной константой, несмотря на то, что более точное значение храниться в самом FPU.
Пи = 3.1415926535898
При таком раскладе sin(Pi) не равен 0, но близок к нему.

un4-funeral
24.04.2008, 16:26
да знаю, что в радианах
sin(a/180*M_PI)

a ввожу в градусах
в функцию синус уже радианы отправляет


но ,есил ввести угол 30 градусов, то он роавно 0.5 ответ выдаёт..то есть дело не в погрешности
и не только в C++ такое
пытался заюзать ассембелровскую вставку



double sin_asm(double x)
{
double y;
__asm
{
fld x;
fsin;
fstp y;
}
return y;
}

считает для 0<=x<180 тоже

somewhere
24.04.2008, 16:56
Из последнего поста так и не понял - проблема решена или нет?

un4-funeral
24.04.2008, 17:00
Из последнего поста так и не понял - проблема решена или нет?

нет =/
то есть, как сделать, чтоб решал для всех углов, я могу сделать

Просто хочу разобраться, в чём конкретно загвостка...не гоже так бросать

somewhere
24.04.2008, 21:59
чему точно равно M_PI можно посмотреть?

un4-funeral
24.04.2008, 22:07
на экран вывести ) M_PI типа double

3,14159265358979

somewhere
24.04.2008, 22:41
Сейчас пробовал сам, константа типа double может хранить число Пи лишь с точностью до 15 знака, остальные что идут после числу Пи не пренадлежат либо равны 0. Соответственно Sin(Pi) дает результат с "погрешностью" до 15-16 знаков, т.к. при вычислении синуса задействуется FPU, а он как известно работает с 10-байтовыми числами, а значит вычисляет точнее, т.к. M_PI все же меньше чем Пи, не так ли?

un4-funeral
24.04.2008, 23:31
ну получается, что так

проблему синуса я вобщем-то решил
если кому-нить надо, воть


/*
Вычисление синуса
На входе: a - типа double(угол в градусах)
На выходе: синус угла
*/
double sin_rad_grad(double x)
{
double intpart;
modf(x/360,&intpart);
if (abs(intpart)>0)
{
if (x<0) x=x-360*intpart;
else x=x+360*intpart;
}
if (x<0) x=x+360;
if ((x>=0) && (x<180)) return sin(x*M_PI/180);
if ((x>=180) && (x<360)) return -sin((x-180)*M_PI/180);
}


считает для любого угла...ну главное, чтоб double вместить мог (((:

somewhere
25.04.2008, 09:02
Это просто глупо, т.к. FPU сам следит за периодом и знаками и никаких тут проверок и кучи кода не надо. У меня такое чувство что вы в Microsoft'е работаете.


double sin_grad(double x)
{
double y,c;
c = 180;
__asm
{
fldpi;
fmul x;
fdiv c;
fsin;
fstp y;
}
return y;
}

Значение X в градусах не должно быть больше 2^63 / PI * 180, что успешно отсеивается типом Double

un4-funeral
25.04.2008, 15:09
Это просто глупо, т.к. FPU сам следит за периодом и знаками и никаких тут проверок и кучи кода не надо. У меня такое чувство что вы в Microsoft'е работаете.


double sin_grad(double x)
{
double y,c;
c = 180;
__asm
{
fldpi;
fmul x;
fdiv c;
fsin;
fstp y;
}
return y;
}

Значение X в градусах не должно быть больше 2^63 / P086I * 180, что успешно отсеивается типом Double


ну и ?
введя 180 градусов, он выводит ответ -5, 42101086242752E-20
а должно 0
у меня по крайне мере точно всё выводит, хотя и не рационально

somewhere
25.04.2008, 15:54
Я не знаю как у вас, у меня лично 0. Вы какой функцией результат смотрите?

un4-funeral
25.04.2008, 16:46
somewhere, MessageDlg например

somewhere
25.04.2008, 21:45
MessageDlg функция вывода текстового сообщения, мне интересно знать функцию перевода из double в строку

olympian
25.04.2008, 21:48
MessageDlg функция вывода текстового сообщения, мне интересно знать функцию перевода из double в строку

хм, а что трудного?
Банально - 1)Приводим к INT - отсекая дробную часть, выводим INT.Это не сложно.
2)Дробная часть - делаем так 0.xyz... * 10 = x.yz приводим к инту, получаем x. - выводим.Так делаем несколько раз

olympian
25.04.2008, 21:51
upd

чтото я ступил конечно=)
простой sprintf(Buf, "%lf", x);
Где Buf - строка, х - наша переменная

somewhere
26.04.2008, 15:00
Я не спрашиваю как, я спросил у un4-funeral как он смотрит результат

un4-funeral
26.04.2008, 20:40
somewhere,
MessageDlg((AnsiString)sin_grad(180),mtInformation ,TMsgDlgButtons()<<mbOK,NULL);

un4-funeral
29.04.2008, 06:55
somewhere, ну так как? -___+