Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > .NET для новичков > Math Sin, Cos, Tan


Автор: Dino99rus 27.10.2007, 01:34
Math.Cos(Math.PI); //-1
Math.Tan(Math.PI); //1
Math.Sin(Math.PI); //1.2......E-16  а должно быть 0

Также операции по вычислению градусов синуса не правельно работает. 
VS2005
В чем подвох. 

Автор: VisualProgrammerNET 27.10.2007, 02:36
М.б. код сих вычислений представишь? 

Автор: Dino99rus 27.10.2007, 02:50
Код

        private void FunctionSin(double b)
        {

            if (Degree.Checked == true)
                stackChis2.Push(Math.Sin(b * Math.PI / 180));
            else
                if (Radian.Checked == true)
                    stackChis2.Push(Math.Sin(b));//через переменную b  передаю значение PI
             
        }
        private void FunctionCos(double b)
        {
                if (Degree.Checked == true)
                    stackChis2.Push(Math.Cos(b * Math.PI / 180));
                else
                    if (Radian.Checked == true)
                        stackChis2.Push(Math.Cos(b));                
        }
        private void FunctionTg(double b)
        {           
                if (Degree.Checked == true)
                    stackChis2.Push(Math.Tan(b * Math.PI / 180));
                else
                    if (Radian.Checked == true)
                        stackChis2.Push(Math.Tan(b));           
        }


Cos и Tan считает нормално, но с Sin касячет

Автор: maxim1000 27.10.2007, 09:42
Цитата(Dino99rus @  27.10.2007,  01:34 Найти цитируемый пост)
Math.Sin(Math.PI); //1.2......E-16  а должно быть 0

в компьютере действительные числа представляются неточно
потому и происходят погрешности вычислений
10^-16 не такая уж и плохая погрешность для большинства задач

Автор: CYBERDREAM 27.10.2007, 09:49
Тогда как выход, округление с заданной степенью точности

Автор: marcusmae 27.10.2007, 12:50
Dino99rus, тригонометрические функции - одни из наиболее ёмких и неточных : для их вычисления используются разложения в ряды. Если интересно, можно разложить синус в ряд Тейлора и посмотреть, какие значения получаются при различной точности. Можно посмотреть готовые http://pasadvice.narod.ru/sum.htm.

Автор: Bogdan1024 27.10.2007, 13:11
Код

double Sin(double a) {
return ((a == Math.PI)? 0 : Math.Sin(a));
}

Такое устраивает?

Автор: Dino99rus 27.10.2007, 15:12
Bogdan1024, 
нет

А если Sin 180 (в градусах), Tan 270 (в градусах) то тоже касяк и т.д..

выходом из такой ситуации я вижу только такой.
Код

double d=1E-15;
if (d > Math.Abs(Math.Sin(b)))
          stackChis2.Push(0);
else
          stackChis2.Push(Math.Sin(b));


Но это будет 3-й касяк С# и меня это удручает.

Автор: marcusmae 27.10.2007, 15:39
Dino99rus, простите, что встреваю, но при чём тут градусы?
Там всё считается в радианах (не в градусах и даже не в градах).
  •  градус = Math.Pi / 180
  •  града = Math.Pi / 200

Таким образом,

Код

Sin(1.5 * Math.Pi); // синус 270


В чём проблема?

Вас не устраивает точность? = Думаю, что если обратиться к другим языкам, будет что-то очень похожее. Никаких косяков тут нет.

Если формальная постановка Вашей задачи позволяет минимизировать использование тригонометрии, логарифмов и экспонент, то это лучше сделать воизбежание лишних недоразумений  smile

Вот это, извините,
Код

double d=1E-15;
if (d > Math.Abs(Math.Sin(b)))
          stackChis2.Push(0);
else
          stackChis2.Push(Math.Sin(b));


выглядит жутковато : как будто синус угла близкого (но не равного) нулю градусам становится равен нулю... Введите b = 1e-15. Получается, вносится ещё и дополнительная потеря точности.

З.Ы. : Вам известен замечательный предел :
user posted image ? smile 

Автор: Dino99rus 27.10.2007, 16:01
marcusmae,
Цитата(marcusmae @  27.10.2007,  15:39 Найти цитируемый пост)
Если формальная постановка Вашей задачи позволяет минимизировать использование тригонометрии, логарифмов и экспонент, то это лучше сделать воизбежание лишних недоразумений 

ну вообще-то, то что я делаю, называется калькуляторsmile (забитая тем, но пишу для себя т.к. не устраивает виндовский). Будет на подобии инженерного (да и так легче изучать язык). Но не суть в этом. Ну кто ни будь, захочет подсчитать Sin 180, Tan 180, Sin Pi, Tan(Pi) и т.п.  и увидит такой ответ (что это ноль). Если продолжать вычисления с этим, результатом, то ошибка будет увеличивать. Например: Tan(180)*10000.   то ошибка будет увеличивать. Например Tan(180)*10000.    

Цитата(marcusmae @  27.10.2007,  15:39 Найти цитируемый пост)
Там всё считается в радианах (не в градусах и даже не в градах).

ну так я там перевожу в градусы.


Цитата(marcusmae @  27.10.2007,  15:39 Найти цитируемый пост)
Вас не устраивает точность? 

да.

Цитата(marcusmae @  27.10.2007,  15:39 Найти цитируемый пост)
Если формальная постановка Вашей задачи позволяет минимизировать использование тригонометрии, логарифмов и экспонент, то это лучше сделать воизбежание лишних недоразумений 


Цитата(marcusmae @  27.10.2007,  15:39 Найти цитируемый пост)
выглядит жутковато : как будто синус угла близкого (но не равного) нулю градусам становится равен нулю... Введите b = 1e-15. Получается, вносится ещё и дополнительная потеря точности.

Вы предлагаете сравнивать входимое значение с углами при которых они  равены 0?

Автор: marcusmae 27.10.2007, 16:08
Понятно.

Ну, в ладонных калькуляторах, насколько можно судить, применяется ровно то, что предложил Bogdan1024 : по всем "хорошим" углам, вместо того, чтобы считать, машинка выдаёт известные точные значения. Это, видимо, как раз и сделано для того, чтобы не смущать обывателей  smile  а то ведь завалят жалобами на "плохие" калькуляторы smile 

... а для произвольных углов будет происходить то, что Вы описали. Машинная точность - она повсюду. Другое дело, что машины считают не абы как, а следуя http://www.iso.org/iso/home.htm-шным стандартам. 

Автор: Dino99rus 27.10.2007, 16:15
marcusmae, 
Цитата(marcusmae @  27.10.2007,  16:08 Найти цитируемый пост)
по всем "хорошим" углам, вместо того, чтобы считать, машинка выдаёт известные точные значения.

и этого никак не избежать
Цитата(marcusmae @  27.10.2007,  16:08 Найти цитируемый пост)
... а для произвольных углов будет происходить то, что Вы описали. Машинная точность - она повсюду. Другое дело, что машины считают не абы как, а следуя ISO-шным стандартам. 

Не понял то Вы говорите, что как я написал не корректно, то это сойдет. 
Мне хотелось бы точно знать, как можно минимизировать погрешность

Автор: marcusmae 27.10.2007, 16:19
Цитата(Dino99rus @  27.10.2007,  16:15 Найти цитируемый пост)
и этого никак не избежать


Возьмите формулы разложений синуса, косинуса, и Вы поймёте, почему это происходит.
Если придумаете более точные алгоритмы для произвольных углов - впервые дадут Нобелевскую премию по математике - это как минимум  smile

Автор: Dino99rus 27.10.2007, 16:24
marcusmae, 
прошу прощении за офтом. Я там выше отредоктировал прочти.

Автор: marcusmae 27.10.2007, 16:32
Цитата(Dino99rus @  27.10.2007,  16:01 Найти цитируемый пост)
Вы предлагаете сравнивать входимое значение с углами при которых они  равены 0?


Нет, я сомневаюсь в состоятельности приведённого Вами кода с условием на малость (и привёл тому пример), предлагаю явно забить условия для известных углов :

Код

double b = ...;

switch (b)
{
case 0 : return 0;
case Math.PI : return 0;
case 0.5 * Math.PI : return 1;
case 1.5 * Math.PI : return -1;
default : return Math.Sin(b);
}


, а в остальном расслабиться.

Автор: Dino99rus 27.10.2007, 16:40
Думаю вопрос исчерпас. Набиру 100 постов и всем плюсику поставлю кто помагал в решении проблем.

Автор: Wizard_Memfis 28.10.2007, 17:42
Полностью поддержую marcusmae, это будет именно то, что нужно!Кстати нам препод говорил, что действительно в калькуляторах так и забивают известными значениями!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)