Конференция "Начинающим" » Вычислить синус и косинус
 
  • dmk © (08.04.18 15:03) [0]
    Всем привет. Требуется вычислить синус и косинус.
    Формула известна: Sin A = X/Radius, Cos A = Y/Radius.
    Отсюда вопрос: как получить величину X и Y, если известен только угол?
    Тут картинка: https://yadi.sk/i/UdcTmWDS3UDDGB
  • Pavia © (08.04.18 15:28) [1]
    Если радиус неизвестен, то никак.
    Radius Sin A = X
    Radius Cos A = Y

    А если нужно вычислить Sin A =  и Cos A =
    то надо использовать ряд Тейлора.
    https://ru.wikipedia.org/wiki/Тригонометрические_функции
  • dmk © (08.04.18 16:03) [2]
    Мне надо понять откуда берутся формулы вроде Sqrt(2.0) / 2.0 = 0,7071067....
    Как вычислить откуда взялась двойка и почему надо делить корень из двух на двойку при 45°, например.
  • dmk © (08.04.18 16:04) [3]
    >Если радиус неизвестен, то никак.
    Радиус известен. Он равен единице.
    На крайний случай можно взять любое простое число. Например 7.
  • Pavia © (08.04.18 16:24) [4]
    Из того что углы по 45  следует что X=Y
    Из теоеремы пирфогора R=sqrt(x^+y^2)
    Тогда sin A=X/R=X/sqrt(x^+y^2)
    X/sqrt(2X^2)=x/{sqrt(2)x}=1/sqrt(2)
    домножаем на sqrt(2) числитель и знаменатель
    sqrt(2)/2
  • Redmond (08.04.18 16:29) [5]
    Нагрузить сопроцессор?
    Использовать любое разложение в ряд?
    Завести таблицу готовых ответов?
  • Pavia © (08.04.18 17:04) [6]
  • dmk © (08.04.18 21:29) [7]
    Спс всем. Сделал через ряды Тейлора.
  • Dimka Maslov © (10.04.18 23:29) [8]
    Просто интересно, а чем не угодили функции sin, cos и SinCos?
  • dmk © (11.04.18 09:06) [9]
    >Просто интересно, а чем не угодили функции sin, cos и SinCos?
    Да всем угодили. Просто тему «поковырял». Стало интересно как сделать это без процессора. Оказывается можно.
  • KSergey © (11.04.18 11:24) [10]
    > dmk ©   (11.04.18 09:06) [9]
    > Стало интересно как сделать это без процессора. Оказывается можно.

    Одно мне не понять: почему бы так сразу вопрос и не поставить? ;)

    ("без процессора" - это, конечно, не совсем удачная фраза, в вопросе если бы она была - то всё ушло бы не туда, аккуратнее тут бы надо.)
  • SergP © (11.04.18 23:08) [11]
    Кстати, вот такая штука еще есть, например:

    ...
    var
     a:array[0..200] of extended;

    implementation

    procedure FillArr;
    var
    k:extended;
    i:integer;
    begin
    a[0]:=0;
    a[1]:=0.01;
    k:=1.9996;
    for i:=2 to 200 do a[i]:=k*a[i-1]-a[i-2];
    end;
    ...


    Угадайте, что за массив мы получим?
  • KilkennyCat © (11.04.18 23:35) [12]
    тангенс?
  • dmk © (11.04.18 23:40) [13]
    Вот например так можно:

    //На входе угол в градусах, результат в радианах
    function Sin_Taylor(X: Double): Double;
    const
     OneD: Double = 100000000000000.0; //14 разрядов точности
     OneM: Double = 0.00000000000001;

    var
     N: Integer;
     sqrX, Cur, Ret: Double;
     K, K2: Integer;
     radX: Double;

    begin
     Ret := 0.0;
     radX := NormalizeAngle(X) * DegToRadD;

     N := 10 + 2 * Abs(Trunc(radX));
     radX := TruncD(OneD * radX);
     Cur := radX;
     SQRX := (radX * radX);

     for K := 0 to N do
     begin
       Ret := (Ret + Cur);
       K2 := (K shl 1);
       Cur := FloorDiv(-Cur * SQRX, (K2 + 2) * (K2 + 3) * OneD * OneD);
     end;

     Result := (Ret * OneM);
    end;

    //На входе угол в градусах, результат в радианах
    function Cos_Taylor(X: Double): Double;
    const
     Epsilon: Double = 0.00000000000001;

    begin
     Result := Sin_Taylor(NormalizeAngle(X) - 90.0);
     if Abs(Result) <= Epsilon then Result := 0.0;
    end;


    Функция не моя. Подсказали.
  • dmk © (11.04.18 23:42) [14]
    Теперь вот полиномами занимаюсь. Вариантов вычисления синуса и косинуса вагон и маленькая тележка. Думаю пока какой полином выбрать. Говорят полиномы Чебышёва самые точные в районе нуля.
  • SergP © (12.04.18 00:19) [15]

    > KilkennyCat ©   (11.04.18 23:35) [12]
    >
    > тангенс?


    В данном случае массив синусов с шагом 0,01 (около 0,57 градуса)
  • KilkennyCat © (12.04.18 00:36) [16]

    > SergP ©   (12.04.18 00:19) [15]

    эх,не угадал. я думал, что раз синусы и косинусы уже были, то вероятность тангенса высока )
  • kilkennycat © (12.04.18 00:38) [17]

    > SergP ©   (12.04.18 00:19) [15]

    и, кстати, спасибо. Пригодится.
  • SergP © (12.04.18 10:58) [18]

    > kilkennycat ©   (12.04.18 00:38) [17]
    >
    >
    > > SergP ©   (12.04.18 00:19) [15]
    >
    > и, кстати, спасибо. Пригодится.


    Кстати, тут небольшая ошибочка (из-за нее амплитуда синусоиды уменьшается в 2 раза а частота увеличивается в 2 раза):

    >  k:=1.9996;

    при шаге 0,01 оно должно быть равным 1,9999

    A[0]:=0;       // sin(0)=0
    A[1]:=0.01;   // Берем шаг delta=0.01, A[1]:=sin(delta), а учитывая первый замечательный предел sin(0.01)~0.01
    k=1.9999;   //k:=2*cos(delta) или k:=2*sqrt(1-delta*delta)

  • kilkennycat © (12.04.18 15:37) [19]

    > из-за нее амплитуда синусоиды уменьшается в 2 раза а частота
    > увеличивается в 2 раза

    именно это и нужно.
  • dmk © (12.04.18 20:12) [20]
    Во как еще синус считают:

    function Sin_APX(X: Double): Double;
    begin
     X := X / (2.0 * PI);
     X := X - Round(X);
     X := X * 7.59 * (0.5 - Abs(X));
     Result := (1.634 + Abs(X)) * X;
    end;


    Но точность у нее всего 1e-2. На 3-м знаке уже расхождение.
    Тут онлайн компилято посмотреть:
    http://rextester.com/DALIFZ95838
  • kilkennycat © (13.04.18 03:45) [21]

    >  точность у нее всего 1e-2

    ну. для некоторых решений более чем. иногда важнее быстрый и простой (незатратный по ресурсам) расчет.
  • dmk © (13.04.18 12:34) [22]
    Мне нужен точный расчет. 1e-14 и более. Не знакомы с методами?
  • Inovet © (13.04.18 13:46) [23]
    > [22] dmk ©   (13.04.18 12:34)
    > Мне нужен точный расчет

    Ряды пробовал, не подходят, не предлагать. Так?
  • Inovet © (13.04.18 13:48) [24]
    И ты думаешь сопроцессор вычисляет молитвой?
  • SergP © (13.04.18 14:10) [25]

    > dmk ©   (13.04.18 12:34) [22]
    >
    > Мне нужен точный расчет. 1e-14 и более. Не знакомы с методами?
    >


    Для быстрого и точного расчета есть сопроцессор.
    Для познавательных целей есть ряды, цепные дроби и т.д.
    А Вам для чего нужно?
  • dmk © (13.04.18 14:12) [26]
    >Ряды пробовал, не подходят, не предлагать. Так?
    Ряды очень неточные. Их вообще лучше не использовать. Это приближенный метод.

    Процессоры работают через CORDIC или полиномы Чебышёва.
  • dmk © (13.04.18 14:31) [27]
    >In the 1990s Intel replaced the 8087’s CORDIC-based approximations of the elementary
    >transcendental functions with polynomial-based approximations.

    Вот примерно так. Может и не Чебышев конечно. Вряд ли они раскажут.
  • dmk © (13.04.18 14:40) [28]
    >А Вам для чего нужно?
    Чтобы было )
  • Inovet © (13.04.18 14:51) [29]
    > [26] dmk ©   (13.04.18 14:12)
    > Это приближенный метод.

    Все методы приближённые. Ряды неточные так же как и всё остальное, потому что иррациаональные числа не представимы через целые, и с плавающей точкой, которые тоже целые по сути с некоторым усовершенствованием. Но могут быть вычеслены с любой точностью. В чём проблема? Остальное уже усовершенствования и оптимизация.
  • Redmond (13.04.18 18:46) [30]
    Вы уверены? Подобная точность требуется менее чем в 0.25% случаев.
    А по поводу оптимизаций - сопроцессор если что уметь одновременное вычисление значения синуса и косинуса.
    И ещё вот: https://stackoverflow.com/questions/2683588/what-is-the-fastest-way-to-compute-sin-and-cos-together
  • SergP © (13.04.18 19:06) [31]
    Возник тут в мозгу весьма интересный вариант как посчитать синус, но судя по всему он не будет быстрым...

    Но если нужно для наглядности, могу попробовать эту мысль преобразовать в код на Delphi.
  • SergP © (13.04.18 20:04) [32]
    Вот что получилось
    Аргумент передается в виде целого числа, размерность которого определяется первоначальными присвоениями значений sn и сs

    Допустим мы передаем на вход функции кол-во тысячных долей радиан, тогда:
    sn:=sin(0.001)
    cs:=cos(0.001)

    ну и аргумент должен быть >=0, иначе нужно доработать код учитывая нечетность функции синуса

    function sinus(source:integer):extended;
    var
     sn,cs,sres,cres:extended;
    begin
     sn:=0.000999999833333341666666468253971;
     cs:=0.99999950000004166666527777780258;
     Result:=0;
     cres:=1;
     while source>0 do
     begin
       if source and 1 = 1 then
       begin
         sres:=Result;
         Result:=sres*cs+cres*sn;
         cres:=cres*cs-sres*sn;
       end;
       sn:=2*sn*cs;
       cs:=2*cs*cs-1;
       source:=source shr 1;
     end;
    end;


    Количество итераций цикла равно количеству значащих двоичных разрядов аргумента.
    Сверялся с калькулятором. Точность довольно неплохая.
    Например значение функции при аргументе 100000 (т.е. 100 радиан) равно -0,506365641097155
    А калькулятор говорит что:
    -0,50636564110975879365655761045979
  • dmk © (14.04.18 03:05) [33]
    Пока будет считать CPU:

    function Cos(A: PDouble): Double;
    asm
     fld qword ptr [A]
     fcos
     fstp qword ptr [Result]
    end;


    Точности хватает.
  • Inovet © (14.04.18 07:31) [34]
    > [33] dmk ©   (14.04.18 03:05)
    > Пока будет считать CPU:

    Ты в который раз про процессор и всё время что-то не то. Может быть, ты хотел написать "FPU"?

    И про точность тоже не ясно, я же выше написал - с любой точностью. Понятно, что надо арифметику расширенную до нужной точности сделать.
  • dmk © (14.04.18 12:08) [35]
    >Может быть, ты хотел написать "FPU"?

    FPU находится в CPU ...
    Каламбур© ;)
  • dmk © (14.04.18 12:11) [36]
    Хотя помню для 386DLC покупали отдельный сопроцессор Cyrix.
    Получался 386DX-40 ;)
  • Inovet © (14.04.18 12:18) [37]
    > [36] dmk ©   (14.04.18 12:11)

    Плохо помнишь.
  • Redmond (14.04.18 14:42) [38]
    Грубо говоря CPU и FPU склеили вместе - но всё равно это разные системы, термины "процессор" и "сопроцессор" разные, и команды у них разные. FCOS - это команда сопроцессора (FPU).

    Всё же рассмотрите команду FSINCOS.
  • KilkennyCat © (14.04.18 19:55) [39]
    если говорить про алгоритмы, то упоминать о какихто склеенных фпу нетолератно по отношению к другим процессорам, например, PIC10F200
  • dmk © (15.04.18 12:09) [40]
    Пока сделал так:
    function _Cos(A: PDouble): Double;
    asm
     .NOFRAME

     fld qword ptr [A]
     fcos
     fstp qword ptr [Result]
    end;

    function _Sin(A: PDouble): Double;
    asm
     .NOFRAME

     fld qword ptr [A]
     fsin
     fstp qword ptr [Result]
    end;

    Работает, но нужно обрабатывать исключения. Часто выдает -1,#IND.
    Есть у кого опыт с обработкой исключений?
 
Конференция "Начинающим" » Вычислить синус и косинус
Есть новые Нет новых   [91044   +18][b:0.001][p:0.004]