Конференция "Начинающим" » Быстрое вычисление приблизительного значения синуса. [D7, XP]
 
  • D7 (28.03.17 16:27) [0]
    Здравствуйте!
    Может у кого-то завалялась готовая функция/либа для быстрого приблизительного расчёта синуса? Типа по приближённым формулам или из таблицы?
    Стандартный дюже долго думает, а мне и не надо большой точности.
    Надо кое-то быстро протестить, а делать свой велосипед с нуля долго и не факт что сделаю достаточно оптимально, а гугл что-то шлёт не в тему.
    Спасибо!
  • rrrrr © (28.03.17 16:46) [1]
    синус приблизительно равен косинусу. погрешность меньше единицы
  • Sha © (28.03.17 17:00) [2]
    что мешает заполнить таблицу и брать значения из нее?
  • D7 (28.03.17 17:05) [3]
    Жуткая спешка и врождённая непереносимость тригонометрии. :3

    Пока так набросал, но что-то нифига не улучшилось:

    Unit FastSinCos;

    Interface

    Function FastSinTable(Const X: Real): Real;

    Implementation

    Var SinTable: Array [-3000 .. 3000] Of Real;

    Procedure InitSinTable();
    Var X: Integer;
    Begin
    For X:=Low(SinTable) To High(SinTable) Do
         SinTable[X]:=Sin(X/10);
    End;

    Function FastSinTable(Const X: Real): Real;
    Begin
    Result:=SinTable[Trunc(X*10)];
    End;

    Initialization

    InitSinTable();

    Finalization

    End.


    Или я совсем криволапый, или тормозит не там где ожидалось... гм...
  • rrrrr © (28.03.17 18:11) [4]
    это типа синусы для градусов цельсия?
    круто
  • Юрий Зотов © (28.03.17 20:06) [5]
    Если я еще не совсем забыл Delphi, то нужно просто заменить Real на Extended и использовать стандартную Sin. То есть, заставить работать сопроцессор, а быстрее него вряд ли что придумаешь.
  • rrrrr © (28.03.17 20:33) [6]
    просто интересно, зачем таблица синусов длиной в 600 радиан.
  • rrrrr © (28.03.17 20:33) [7]
    просто интересно, зачем таблица синусов длиной в 600 радиан.
  • Kilkennycat © (28.03.17 20:39) [8]

    > rrrrr ©   (28.03.17 20:33) [7]

    слишком короткая?
  • rrrrr © (28.03.17 20:43) [9]
    в военное время на сотом обороте говорят значения синуса начинают плавать
  • dmk © (28.03.17 20:46) [10]
    Смысла в таблице нет. Процессоры Pentium II-III и выше считают синус быстрее чем чтение из таблицы (памяти). Так что если что-то вращать надо то вот:



    type
     PFloatPoint = ^TFloatPoint;
     TFloatPoint = record
       fX, fY: double;
       end;

    const
     PIdiv180: float = (PI / 180);

    function RotatePoint(Angle: Float; cP, dP: TFloatPoint): TFloatPoint;
    var
     lpSin, lpCos: Float;
     P: TFloatPoint;
     lpRad: Float;

    begin
     lpRad := Angle * PIdiv180;
     lpSin := Sin(lpRad);
     lpCos := Cos(lpRad);

     //Смещение к центру вращения
     P.fX := dP.fX - cP.fX;
     P.fY := dP.fY - cP.fY;

     //Вращение точки и возврат на место
     Result.fX := (P.fX * lpCos - P.fY * lpSin) + cP.fX;
     Result.fY := (P.fX * lpSin + P.fY * lpCos) + cP.fY;
    end;
  • dmk © (28.03.17 20:48) [11]
    CP - центр вращения
    DP - удаленная точка
  • D7 (28.03.17 21:19) [12]
    > просто заменить Real на Extended

    Ничего не изменилось.

    > просто интересно, зачем таблица синусов длиной в 600 радиан.

    Просто рантайм замерял минимальную и максимальную значению того что в моём конкретном случае может передаваться в SinEx(): [ -217,21 .. 247,96 ] - и эдак округлил в большую сторону. %) Для наколенного теста сойдёт)

    > заставить работать сопроцессор, а быстрее него вряд ли что придумаешь.

    Вроде ж как как минимум приближённый на процессоре быстрее чем тот что на сопроцессоре (который делает с этакой хорошей точностью), не?

    > считают синус быстрее чем чтение из таблицы

    Почему вдруг?


    Короче придётся выкидывать выходной и мерять скорость выполнения и точность разных вариантов по старинке...
  • rrrrr © (28.03.17 21:26) [13]
    о я понял всю гениальность замысла

    чувак одной таблицей убивает двух зайцев.
    1. подменяет медленный sin
    2. длинной таблицы подменяет медленный x mod 2pi
  • rrrrr © (28.03.17 21:27) [14]
    осталось заменить четыре арифметических на таблицы брадиса и логлинейку

    вообще летать будет
  • dmk © (28.03.17 21:28) [15]
    >Почему вдруг?
    SSE -  1 такт
  • D7 (28.03.17 21:45) [16]
    Я же написал - у меня непереносимость тригонометрии. Не понимаю я эти радианы, чтоб их. Помню тока что 2pi это окружность или её половина.
    гм... mod 2pi, спасибо, звучит логично, ток а ничё что "x" и "2pi" в плавающие?)

    > SSE -  1 такт

    И давно ли Делфи7 выполняет Sin() при помощи SSE?)))
    А текущие версии серьёзно на нём чтоле? о___О
  • rrrrrr (28.03.17 22:05) [17]
    плавающие и чо.
    плавающий остаток от деления на круг никуда не делся
  • dmk © (28.03.17 22:06) [18]
    Нельзя писать то, чего не понимаешь. Это бред какой то.
    Лучше не программировать тогда. Радианы в школе проходят.

    Вот синус:
    PIdiv180: double = (PI / 180);
    lpSin := Sin(Angle * PIdiv180);

    >И давно ли Делфи7 выполняет Sin() при помощи SSE?)))
    Давно. Где то с 2005-2009-й версии. В Д7 нету. Там ФПУ. Но можно байт-коды забить в ASM.
    SSE - быстрее чем ФПУ из-за отсутствия подготовки и типа double.
    Если Extended не нужен - то SSE -лучше всего и быстрее.
  • D7 (28.03.17 22:28) [19]
    > плавающие и чо.

    Дак вот чё:
    procedure TForm1.Button1Click(Sender: TObject);
    const pi2: Double = PI*2;
    var x: Double;
    begin
    x:=-217.21;
    x:=x mod pi2;
    end;


    [Error] Unit1.pas(75325): Operator not applicable to this operand type

    Вполне ожидаемо. А мне проще сделать таблицу от -300 до 300 чем непонятно как подгонять радианы, ломать голову на чего их домножать там.
 
Конференция "Начинающим" » Быстрое вычисление приблизительного значения синуса. [D7, XP]
Есть новые Нет новых   [118240   +21][b:0][p:0.001]