Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Sin быстрее чем из math.h 
:(
    Опции темы
Staskot
Дата 3.2.2012, 17:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



ребят, вообщем мне задали написать программу которая считала синус быстрее чем из math.h ) скорость должна достигаться путем потери точности) Я вот написал код который(как я думаю должен быстрее работать) но на деле не вижу что он быстрее) подтолкните кто нить)
Код

#include <iostream>
#include <conio.h>
#include <math.h>
#include <windows.h>
const int N=100000;
void main(void)
{int i;
double x1,x2,y,z;
x1=1.0; x2=2.0-1.0e-10;// вот здесь я обрезаю точность до 10 знаков 
y=(x2-x1)/N;
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);

LARGE_INTEGER time1;
QueryPerformanceCounter(&time1);
for(i=0,z=x1;i<N;i++,z+=y)
{
sin(z);
}
LARGE_INTEGER time2;
QueryPerformanceCounter(&time2);
time2.QuadPart -= time1.QuadPart;
double span = (double) time2.QuadPart / freq.QuadPart; 
printf( "for sin time: %f seconds\n", span );
getch();
} 

PM MAIL   Вверх
borisbn
Дата 3.2.2012, 17:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



Цитата(Staskot @  3.2.2012,  17:21 Найти цитируемый пост)
// вот здесь я обрезаю точность до 10 знаков 

Здесь ты изменяешь шаг аргумента функции sin, да и то, по-моему, неправильно. Функция sin всё равно вызывается N раз. И (самое главное) тебе ж сказали

Цитата(Staskot @  3.2.2012,  17:21 Найти цитируемый пост)
написать программу которая считала синус быстрее чем из math.h 

а ты берёшь функцию sin из этого самого math.h  smile 

Короче, тебе нужно написать свою функцию вычисления синуса. Погугли "разложение синуса в ряд с заданной точностью". Ну или что-то в этом роде.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Фантом
Дата 3.2.2012, 18:27 (ссылка) |    (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 4
Всего: 49



Цитата(Staskot @  3.2.2012,  18:21 Найти цитируемый пост)
ребят, вообщем мне задали написать программу которая считала синус быстрее чем из math.h ) скорость должна достигаться путем потери точности)

А более точной формулировки задания нет? А то ведь можно написать 
Код

float sin(float x)
{
return 0.0;
}

и это будет быстро и с абсолютной погрешностью не больше единицы.  smile 
PM   Вверх
borisbn
Дата 3.2.2012, 18:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



Фантом, у тебя погрешность м.б. больше единицы, т.к. ты преобразуешь double в float (return 0.0;)
Надо
Цитата

float sin(float x)
{
return 0.0f;
}

 smile 
прикалываюсь, ессно


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Фантом
Дата 3.2.2012, 20:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 4
Всего: 49



Цитата(borisbn @  3.2.2012,  19:30 Найти цитируемый пост)
т.к. ты преобразуешь double в float (return 0.0;)

Именно для нуля не страшно.  smile 
PM   Вверх
feodorv
Дата 3.2.2012, 21:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(Staskot @  3.2.2012,  17:21 Найти цитируемый пост)
Я вот написал код

Гм. Приведённый код считает производительность стандартной функции sin, но нет даже намёка на собственную
Цитата(Staskot @  3.2.2012,  17:21 Найти цитируемый пост)
программу которая считала синус

 smile 


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
volatile
Дата 3.2.2012, 23:48 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Единственно, где есть какая-то надежда обогнать math.h,  это табличный синус.
Да и то я сомневаюсь, что получится обогнать.
Там синус вычисляет мат.сопроцессор. вычисление синуса - его внутренняя комманда.

PM MAIL   Вверх
feodorv
Дата 4.2.2012, 00:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Вот здесь, по-моему, просили вычислить синус с заданной точностью...

Цитата(volatile @  3.2.2012,  23:48 Найти цитируемый пост)
Да и то я сомневаюсь, что получится обогнать

Если точность невысока (относительная ~10-4), то может и обогнать...


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
volatile
Дата 4.2.2012, 01:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Цитата(feodorv @  4.2.2012,  00:12 Найти цитируемый пост)
Если точность невысока (относительная ~10-4), то может и обогнать... 

надо будет замерить как-нибудь..
(иногда возникает необходимость в быстром синусе).
но чисто интуитивно -  что-либо значительного там не добиться...

PM MAIL   Вверх
feodorv
Дата 4.2.2012, 10:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(volatile @  4.2.2012,  01:36 Найти цитируемый пост)
надо будет замерить как-нибудь..


Набросал некоторую программку:
Код

#include <conio.h>
#include <math.h>
#include <windows.h>

double mysin( double value )
{
  double v2 = value * value;
  double step = value * v2 / 6.;
  return value - step + v2 * step / 20.;
}

double mysin2( double value )
{
  double v2 = value * value;
  double step = value * v2 / 6.;
  value -= step;
  step *= v2 / 20.;
  value += step;
  return value - step * v2 / 42.;
}

double mysin3( double value )
{
  double v2 = value * value;
  double step = value * v2 / 6.;
  double step2 = step * v2 / 20.;
  double step3 = step2 * v2 / 42.;
  return value - step + step2 - step3;
}

#define N 100000
#define M 100

enum
{
  SINMIN = 0,
  SINMAX,
  SINAVE,
  SINLAST
};

#define INITIME(tm) \
    (tm)[SINMAX] = (tm)[SINMIN] = (tm)[SINAVE] = 0

#define GETTIME(f,tm) \
  do{ \
    LARGE_INTEGER time1, time2; \
    double z, span; \
    int n; \
    \
    QueryPerformanceCounter( &time1 ); \
    for( n=0,z=y; n<N; n++, z+=y) (f)(z); \
    QueryPerformanceCounter( &time2 ); \
    \
    time2.QuadPart -= time1.QuadPart; \
    span = (double) time2.QuadPart / freq.QuadPart; \
    \
    if( (tm)[SINMAX] < span ) (tm)[SINMAX] = span; \
    if( (tm)[SINMIN] == 0 || (tm)[SINMIN] > span ) (tm)[SINMIN] = span; \
    (tm)[SINAVE] += span; \
  } while(0)

#define PRITIME(tm,fn) \
  printf( "%s time: %f %f %f seconds\n", (fn), (tm)[SINMIN], (tm)[SINMAX], (tm)[SINAVE] / (double) M);

#define SINCHECK

void main(void)
{
  int m;
  double y;
  LARGE_INTEGER freq;
  double ts[SINLAST], ty[SINLAST], ty2[SINLAST], ty3[SINLAST];

  y = 2.0 / (double) N;
  QueryPerformanceFrequency(&freq);
  INITIME( ts );
  INITIME( ty );
  INITIME( ty2 );
  INITIME( ty3 );

#ifdef SINCHECK
  {
    int n; double z;
    for( n=0,z=y; n<N/2; n++, z+=y)
    {
      double m = mysin(z), m2 = mysin2(z), m3 = mysin3(z), s = sin(z);
      if( fabs( (s-m)/z ) > 0.0002 ) printf( "Oops(mysin)... z=%f s=%f m=%f err=%f\n", z, s, m, fabs( (s-m)/z ));
      if( fabs( (s-m2)/z ) > 0.000003 ) printf( "Oops(mysin2)... z=%f s=%f m2=%f err=%f\n", z, s, m2, fabs( (s-m2)/z ));
      if( fabs( (s-m3)/z ) > 0.000003 ) printf( "Oops(mysin3)... z=%f s=%f m3=%f err=%f\n", z, s, m3, fabs( (s-m3)/z ));
    }
    for( n=0,z=1.0; n<N/2; n++, z+=y)
    {
      double m = mysin(z), m2 = mysin2(z), m3 = mysin3(z), s = sin(z);
      if( fabs( (s-m)/z ) > 0.013 ) printf( "Oops(mysin)... z=%f s=%f m=%f err=%f\n", z, s, m, fabs( (s-m)/z ));
      if( fabs( (s-m2)/z ) > 0.0007 ) printf( "Oops(mysin2)... z=%f s=%f m2=%f err=%f\n", z, s, m2, fabs( (s-m2)/z ));
      if( fabs( (s-m3)/z ) > 0.0007 ) printf( "Oops(mysin3)... z=%f s=%f m3=%f err=%f\n", z, s, m3, fabs( (s-m3)/z ));
    }
  }
#endif

  for( m = 0; m < M; m++)
  {
    Sleep(100);
    GETTIME( mysin, ty);
    GETTIME( mysin2, ty2);
    GETTIME( mysin3, ty3);
    GETTIME( sin, ts);
  }

  PRITIME( ts, "sin");
  PRITIME( ty, "mysin");
  PRITIME( ty2, "mysin2");
  PRITIME( ty3, "mysin3");
  getch();
}


Здесь mysin использует первые 3 члена разложения sin в ряд, mysin2 - уже 4, mysin3 - практически то же самое, что и mysin2, но несколько иначе считает сумму.

Результаты. С установленной SINCHECK:
Цитата

sin time: 0.017760 0.047614 0.020920 seconds
mysin time: 0.012157 0.026837 0.013616 seconds
mysin2 time: 0.017722 0.046867 0.019851 seconds
mysin3 time: 0.016511 0.037132 0.018554 seconds


С выключенной SINCHECK:
Цитата

sin time: 0.017547 0.039049 0.020133 seconds
mysin time: 0.012153 0.027060 0.013632 seconds
mysin2 time: 0.017726 0.054278 0.020688 seconds
mysin3 time: 0.018676 0.050791 0.021672 seconds

Гм. Почему так разнятся результаты (а это поведение устойчивое) с SINCHECK и без оной, понять не могу.

В любом случае mysin подходит под условие задачи, причём её точность в диапазоне аргументов -1 <= z <= 1 составляет две сотых процента, а в диапазоне -2 <= z <=2 - полтора процента (этот диапазон не покрывает -pi <= z <= pi, но это другая история).


Цитата(volatile @  4.2.2012,  01:36 Найти цитируемый пост)
но чисто интуитивно -  что-либо значительного там не добиться...

 smile 


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
ksili
Дата 4.2.2012, 13:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2069
Регистрация: 3.11.2005
Где: Красноярск

Репутация: нет
Всего: 17



Где-то я слышал, что обычно вычисляют синус приближением многочленами Чебышева. FPU по-моему так и делает. Но в нём многочлены взяты такого порядка, чтобы получить расширенную точность (максимальная точность FPU). А вам надо взять степень меньше. 

Если найдете материалы по этой теме, киньте ссылку здесь. Мне тоже интересно.


--------------------
Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с)
PM MAIL   Вверх
boostcoder
Дата 4.2.2012, 13:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 20
Всего: 110



Цитата(feodorv @  4.2.2012,  10:56 Найти цитируемый пост)
QueryPerformanceCounter

можно было использовать boost.chrono, чтоб код можно было выполнить не только на венде.

спасибо.

PM WWW   Вверх
feodorv
Дата 4.2.2012, 15:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



 smile Дурная голова ногам покоя не даёт... Не правильно расчитал ошибку  smile  А смайлика, посыпающего голову пеплом, нет?)))

Короче говоря, вместо 
Код
(s-m)/s
 написал 
Код
(s-m)/z


Тогда цифры получаются такие:
Код

    for( n=0,z=y; n<N/2; n++, z+=y)
    {
      double m = mysin(z), m2 = mysin2(z), m3 = mysin3(z), s = sin(z);
      if( fabs( (s-m)/s ) > 0.00024 ) printf( "Oops(mysin)... z=%f s=%f m=%f err=%f\n", z, s, m, fabs( (s-m)/s ));
      if( fabs( (s-m2)/s ) > 0.000004 ) printf( "Oops(mysin2)... z=%f s=%f m2=%f err=%f\n", z, s, m2, fabs( (s-m2)/s ));
      if( fabs( (s-m3)/s ) > 0.000004 ) printf( "Oops(mysin3)... z=%f s=%f m3=%f err=%f\n", z, s, m3, fabs( (s-m3)/s ));
    }
    for( n=0,z=1.0; n<N/2; n++, z+=y)
    {
      double m = mysin(z), m2 = mysin2(z), m3 = mysin3(z), s = sin(z);
      if( fabs( (s-m)/s ) > 0.027 ) printf( "Oops(mysin)... z=%f s=%f m=%f err=%f\n", z, s, m, fabs( (s-m)/s ));
      if( fabs( (s-m2)/s ) > 0.0015 ) printf( "Oops(mysin2)... z=%f s=%f m2=%f err=%f\n", z, s, m2, fabs( (s-m2)/s ));
      if( fabs( (s-m3)/s ) > 0.0015 ) printf( "Oops(mysin3)... z=%f s=%f m3=%f err=%f\n", z, s, m3, fabs( (s-m3)/s ));
    }


То есть, в диапазоне -2 <= z <=2 точность достигает трёх процентов (не полутора). Ну это так, для порядка)))


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Staskot
Дата 4.2.2012, 15:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



feodorv 
хм запустил вашу у программу у себя( VS 2010) вот какие у меня результаты: 
sin time: 0.002971  0.005865  0.003412 seconds
mysin time : 0.006127  0.013735  0.007204 seconds
mysin2 time : 0.007505  0.013541  0.008607 seconds
mysin3 time : 0.008309  0.016118  0.009687 seconds
И ещё я правильно понял что добиться скорости  в 50% нельзя если обрезать до 10 знаков?
PM MAIL   Вверх
feodorv
Дата 4.2.2012, 15:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



По поводу многочленов Чебышева:Добавлено @ 15:56
Цитата(Staskot @  4.2.2012,  15:49 Найти цитируемый пост)
И ещё я правильно понял что добиться скорости  в 50% нельзя если обрезать до 10 знаков? 

Можно как раз попробовать Чебышевкий вариант)))
А обрезано и так до невозможности...
Если у Вас очень малые z (порядка 10-6), то можно просто возвращать z, не заморачиваясь, абсолютная точность до 10 знаков будет обеспечена. Скорость при этом будет обалденная)))
Я так и не понял, в каком место вам нужны эти 10 знаков. Чтобы совпадало с точностью до 10 знаков на диапазоне -2 <= z <= 2 никак встроенный sin не обогнать.

Добавлено @ 15:58
Но у Вас sin более чем в два раза опережает mysin  smile Что и требовалось доказать smile Видимо, новые процессоры, новые сопроцессоры, новые шины, новая частота памяти...

Это сообщение отредактировал(а) feodorv - 4.2.2012, 16:08


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Staskot
Дата 4.2.2012, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



feodorv 
несколько вопросов по коду возникло) как я понял sin из стандартной библиотеки) а mysin ваши функции) а при выводе выдает что стандартный синус быстрее чем ваш синус) извиняюсь за глупые вопросы) просто хочу разобраться)
PM MAIL   Вверх
feodorv
Дата 4.2.2012, 16:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(Staskot @  4.2.2012,  16:35 Найти цитируемый пост)
а при выводе выдает что стандартный синус быстрее чем ваш синус) 

Ага. См. мой предыдущий пост)))



--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Staskot
Дата 4.2.2012, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



Очень жаль) а если попробывать табличный синус) ну и написать что то вроде
Код

//// заголовочный файл
#pragma once
#define MAX_ANGLE 360
class GE_FastMath
{private:    static double mCosTable[MAX_ANGLE];
static double mSinTable[MAX_ANGLE];public:    
static void Initialize();    
static double Cos(int iAngle) 
{ return mCosTable[iAngle]; }    
static double Sin(int iAngle) 
{ return mSinTable[iAngle]; }};
// cpp-файл
#include "StdAfx.h"
#define _USE_MATH_DEFINES
#include <math.h>
#include "GE_FastMath.h"
double GE_FastMath::mCosTable[MAX_ANGLE];
double GE_FastMath::mSinTable[MAX_ANGLE];
void GE_FastMath::Initialize(void)
{    for(int i = 0; i<MAX_ANGLE; i++)   
 {        double lRadian = i * (M_PI / 180); 
       mCosTable[i] = cos(lRadian);       
 mSinTable[i] = sin(lRadian);    }}

PM MAIL   Вверх
Staskot
Дата 5.2.2012, 16:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



ну что ? у кого какие мысли есть?
PM MAIL   Вверх
volatile
Дата 5.2.2012, 23:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



feodorv, спасибо за небольшое исследование.
я примерно так и думал.
А вообще эти задачки написать синус быстрее чем crt-шный идут с допотопных времен.
(учителя еще на турбо С 1.0 пишут, тут это не редкость наблюдать)

Так вот, в те времена, сопроцессор не  был встроен в ЦП, и под него была предусмотрена панелька, которая почти у всех пустовала.
Ну и этот сопроцессор эмулировали программно.
В те времена, когда и учились нынешние преподаватели  smile и была такая задачка, которая банально решалась уменьшением точности.
В наше время, со встроенным сопроцессором, задачка обогнать встроенный синус, превратилась в практически не решаемую. (ну по крайней мере совсем не для начинающих)


Цитата(Staskot @  5.2.2012,  16:02 Найти цитируемый пост)
ну что ? у кого какие мысли есть? 

Staskot, ну так замерьте, и опубликуйте здесь ваши результаты.
кто-ж это кроме вас сделает?

PM MAIL   Вверх
XLAT
Дата 6.2.2012, 12:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 8.1.2012

Репутация: нет
Всего: нет



Все double замени на float
Вот и будет тебе потеря точности(4 байта вместо 8 на одно число) и лишний профит на компенсацию.

можно ещё ассемблерную вставку вставить с соответствующей настройкой CW - регистра управления FPU: 9 и 10 биты сброшены в нуль. Но это если препод разрешит, а, вообще то первого тебе будет достаточно.

PM MAIL   Вверх
Staskot
Дата 6.2.2012, 12:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



вставки нельзя использовать) хоть там и хорошее ускорение будет) double менять на float тоже не вариант) меня заставляют работать только с даблой) вот мучаюсь с табличным синусом) может кто-то поможет мне дописать код?
PM MAIL   Вверх
borisbn
Дата 6.2.2012, 12:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



Цитата(Staskot @  6.2.2012,  12:30 Найти цитируемый пост)
может кто-то поможет мне дописать код?

так уже написан... вызываешь свои же ф-ции GE_FastMath::Sin и GE_FastMath.Cos
Код
double mysin( double x ) {
    GE_FastMath::Sin( (int)x );
}




--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Staskot
Дата 6.2.2012, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



я знаю как дописать чтобы точность была 10 знаков после запятой)
PM MAIL   Вверх
Staskot
Дата 6.2.2012, 13:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



упс)) я НЕ знаю как сделать чтоб точность была именно 10 знаков
PM MAIL   Вверх
Staskot
Дата 6.2.2012, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



Вообщем вот что я имею на данный момент)
Код

//// заголовочный файл
#pragma once
#define MAX_ANGLE 360
class GE_FastMath
{private:    static double mCosTable[MAX_ANGLE];
static double mSinTable[MAX_ANGLE];public:    
static void Initialize();    
static double Cos(int iAngle) 
{ return mCosTable[iAngle]; }    
static double Sin(int iAngle) 
{ return mSinTable[iAngle]; }};
// cpp-файл
#include <iostream>
#include <conio.h>
#include <math.h>
#include <windows.h>
#include "StdAfx.h"
#define _USE_MATH_DEFINES
#include <math.h>
#include "GE_FastMath.h"

const int N=100;
double GE_FastMath::mCosTable[MAX_ANGLE];
double GE_FastMath::mSinTable[MAX_ANGLE];
void GE_FastMath::Initialize(void)
{    for(int i = 0; i<MAX_ANGLE; i++)   
 {        double lRadian = i * (M_PI / 180); 
       mCosTable[i] = cos(lRadian);       
 mSinTable[i] = sin(lRadian);    }}
double mysin( double x ) {
    GE_FastMath::Sin( (int)x );
    return x;
}

void main(void)
{int i;
  double x1,x2,y,z;
x1=1.0; x2=2.0-1.0;
  y=(x2-x1)/N;
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);

LARGE_INTEGER time1;
QueryPerformanceCounter(&time1);
for(i=0,z=x1;i<N;i++,z+=y)
   {
      mysin(z);
 }
LARGE_INTEGER time2;
QueryPerformanceCounter(&time2);
time2.QuadPart -= time1.QuadPart;
double span = (double) time2.QuadPart / freq.QuadPart; 
printf( "for sin time: %f seconds\n", span );
getch();
}

Как я понял это кончательный вариант) вот что получилось для стандартного синуса 0.000022 секунды) а для mysin 0.000012) для меня этот результат хороший) но при больших N  происходит проигрывание mysin, причем ощутимое проигрывание) вообщем вопрос как сделать чтоб точность сохранялась 10 знаков ни больше ни меньше)
PM MAIL   Вверх
bsa
Дата 6.2.2012, 14:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196




 ! 
bsa
Staskot, отформатируй код. Уважай собеседников!!!

PM   Вверх
borisbn
Дата 6.2.2012, 14:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



Цитата(Staskot @  6.2.2012,  14:01 Найти цитируемый пост)
double mysin( double x ) {
    GE_FastMath::Sin( (int)x );
    return x;
}

неправильно. возвращать нужно не x, а
Код
return GE_FastMath::Sin( (int)x );

и ещё где-нибудь в начале main() нужно вызвать GE_FastMath::Initialize();
и ещё: 100 итераций для сравнения времени маловато. сделай 1 млн.

Добавлено через 1 минуту и 37 секунд
P.S. Выводи время в мс (просто умножь на 1e3) - читаеме ж будет


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Staskot
Дата 6.2.2012, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



Цитата(borisbn @  6.2.2012,  14:44 Найти цитируемый пост)
и ещё где-нибудь в начале main() нужно вызвать GE_FastMath::Initialize();
и ещё: 100 итераций для сравнения времени маловато. сделай 1 млн.

Добавлено через 1 минуту и 37 секунд
P.S. Выводи время в мс (просто умножь на 1e3) - читаеме ж будет

Всё равно получается что стандартный синус быстрее чем мой) но это при больших итерациях) а прималеньких мой быстрее)
PM MAIL   Вверх
borisbn
Дата 6.2.2012, 15:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



лови, экспериментируй...
Код

#include <iostream>
#include "TimeMeasure.h"
#include <math.h>

const int MAX_ANGLE = 3600;
const int N = 1000000;
const double Pi = acos( -1.0 );
double tableSin[ MAX_ANGLE ];

void initTableSin() {
    for ( int i = 0; i < MAX_ANGLE; i++ )
    {
        tableSin[ i ] = sin( i / (double)MAX_ANGLE * 360.0 * Pi / 180.0 );
    }
}

double mysin( double x ) {
    return tableSin[ (int)( x / 360.0 * MAX_ANGLE / Pi * 180.0 ) ];
}

double res_math[ N ];
double res_my[ N ];

int main() {
    initTableSin();
    
    double x0 = 0;
    double x1 = 2 * Pi;
    double z = ( x1 - x0 ) / (double)N;
    TimeMeasure math_sin;
    double x = x0;
    for ( int i = 0; i < N; i++, x += z )
    {
        res_math[ i ] = sin( x );
    }
    std::cout << "math::sin time is " << math_sin.elapsed_ms() << " ms" << std::endl;
    TimeMeasure my_sin;
    x = x0;
    for ( int i = 0; i < N; i++, x += z )
    {
        res_my[ i ] = mysin( x );
    }
    std::cout << "my::sin time is " << my_sin.elapsed_ms() << " ms" << std::endl;
    double delta = 0;
    for ( int i = 0; i < N; i++ ) {
        delta += fabs( res_my[ i ] - res_math[ i ] );
    }
    std::cout << "delta is " << delta / (double)N << std::endl;
}



файл TimeMeasure.h:
Код

#if !defined ( _TIMEMEASURE_H_INCLUDED_ )
#define _TIMEMEASURE_H_INCLUDED_

#include <windows.h>

/** \brief Классик для точного измерения времени выполнения чего-либо

    Интерфейс спи..ен с Qt, за исключением того, что в TimeMeasure::TimeMeasure сразу измеряется
    время начала выполнения этого чего-либо :)

    \br
    Пример использования 1:
\code
    TimeMeasure t;
    do_something();
    double msecs_of_something = t.elapsed_ms();
\endcode
    Пример использования 2:
\code
    TimeMeasure t;
    ...
    t.start();
    do_something();
    double mks_of_something = t.elapsed_mks();
\endcode
*/
class TimeMeasure
{
public:
    /** \brief Создание классика измерения
    
        В конструкторе измеряется время начала выполнения чего-либо.
        Его всегда можно измерить заново функцией TimeMeasure::start()
    */
    TimeMeasure()
    {
        QueryPerformanceFrequency( &m_frequency );
        start();
    }
    /// Измерить время начала выполнения чего-либо
    void start()
    {
        QueryPerformanceCounter( &m_startTicks );
    }
    /// Получить разницу времени от функции TimeMeasure::start() до текущего в секундах
    long long elapsed_ticks() const
    {   
        LARGE_INTEGER nowTicks;
        QueryPerformanceCounter( &nowTicks );
        return (nowTicks.QuadPart - m_startTicks.QuadPart);
    }
    /// Получить разницу времени от функции TimeMeasure::start() до текущего в секундах
    double elapsed_sec() const
    {   
        LARGE_INTEGER nowTicks;
        QueryPerformanceCounter( &nowTicks );
        return (nowTicks.QuadPart - m_startTicks.QuadPart) / (double)m_frequency.QuadPart;
    }
    /// Получить разницу времени от функции TimeMeasure::start() до текущего в миллисекундах
    double elapsed_ms() const
    {
        return elapsed_sec() * 1e3;
    }
    /// Получить разницу времени от функции TimeMeasure::start() до текущего в микросекундах
    double elapsed_mks() const
    {
        return elapsed_sec() * 1e6;
    }
private:
    LARGE_INTEGER m_startTicks; ///< Время начала в тиках
    LARGE_INTEGER m_frequency;  ///< Количество тиков в секунду
};
#endif // !defined ( _TIMEMEASURE_H_INCLUDED_ )



--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Staskot
Дата 6.2.2012, 16:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



Цитата(borisbn @  6.2.2012,  15:34 Найти цитируемый пост)
лови, экспериментируй...

Спасибо большое) 
но всё равно при больших итерациях стандартный синус быстрее)
PM MAIL   Вверх
borisbn
Дата 6.2.2012, 16:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



Цитата(Staskot @  6.2.2012,  16:03 Найти цитируемый пост)
но всё равно при больших итерациях стандартный синус быстрее)

и у меня на компе и на LWS mysin быстрее
http://liveworkspace.org/code/963cec3c07a8...bb94dd79915c457


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Staskot
Дата 6.2.2012, 16:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



Цитата(borisbn @  6.2.2012,  16:10 Найти цитируемый пост)
и у меня на компе и на LWS mysin быстрее

насколько сильно время зависит от процессора? у меня на ноуте intel core i3 по 2.27
PM MAIL   Вверх
borisbn
Дата 6.2.2012, 16:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



На моём компе (MSVS 2008)
Цитата

math::sin time is 29 ms
my::sin time is 17 ms
delta is 0.000555748

на LWS
Цитата

math::sin time is 70 ms
my::sin time is 50 ms
delta is 0.000555748


Кста, может ты в Debug-режиме запускаешь ???
Тогда может быть всё, что хочешь. Нужно в Release

Это сообщение отредактировал(а) borisbn - 6.2.2012, 16:33


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Staskot
Дата 6.2.2012, 16:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



Цитата(borisbn @  6.2.2012,  16:31 Найти цитируемый пост)
Кста, может ты в Debug-режиме запускаешь ???
Тогда может быть всё, что хочешь. Нужно в Release

да в дебаге) чесно говоря первый раз слышу про Release )не подскажешь как через него запускать?

Добавлено через 9 минут и 59 секунд
Всё разобрался что такое Releaseи как через него запускать) всё работает) Спасибо))Теперь для полного счастья мучает вопрос) по заданию мне надо чтоб точность было ровно 10 знаков? возможно ли это?
PM MAIL   Вверх
bsa
Дата 6.2.2012, 17:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Staskot, ровно никогда не говорят. Обычно, "не менее 10 знаков". Это разные вещи. Например, синус 0 равен 0. И ты можешь убиться, но точность будет ограничена особенностями типа double (например, больше 10 знаков). 
Если ты хочешь проверить, то делается это очень просто. Модуль разницы между твоим значением и стандартным должен быть меньше 1.0e-10.

Это сообщение отредактировал(а) bsa - 6.2.2012, 17:18
PM   Вверх
Staskot
Дата 6.2.2012, 18:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



Цитата(bsa @  6.2.2012,  17:18 Найти цитируемый пост)
Модуль разницы между твоим значением и стандартным должен быть меньше 1.0e-10.

Т.е в моем случае это будет выглядеть примерно так??
Код

if (abs(mysin( x ) - sin( x ))< 1.0e-10)
     cout << "good ";
else cout << "bad";

PM MAIL   Вверх
feodorv
Дата 6.2.2012, 20:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Прошу прощения, что я опять со своим C)))

Пользуясь формулой
Цитата
sin( x + dx ) = sin(x) * cos(dx) + cos(x) * sin(dx)

и тем, что cos(dx) ~ 1 и sin(dx) ~ dx при малых dx, можно повысить точность вычисления на несколько порядков, потеряв в скорости...

Получилось так:
Код

#include <windows.h>
#include <math.h>

#define PI 3.14159265358
#define MAX_ANGLE (4*1024)

static double tableVal[MAX_ANGLE];
static double tableSin[MAX_ANGLE];
static double tableCos[MAX_ANGLE];

void initTables()
{
  int i;

  for( i = 0; i < MAX_ANGLE; i++)
  {
    tableVal[i] = (double) i / (double) MAX_ANGLE * PI;
    tableSin[i] = sin( tableVal[i] );
    tableCos[i] = cos( tableVal[i] );
  }
}

double mysin( double x )
{
  register int i = (int) (x / PI * (double) MAX_ANGLE);
  return tableSin[i];
}

double mysin2( double x )
{
  register int i = (int) (x / PI * (double) MAX_ANGLE);
  return tableSin[i] + (x - tableVal[i]) * tableCos[i];
}

#define N 1000000
#define M 100

enum
{
  SINMIN = 0,
  SINMAX,
  SINAVE,
  SINLAST
};

#define INITIME(tm) \
    (tm)[SINMAX] = (tm)[SINMIN] = (tm)[SINAVE] = 0

#define GETTIME(f,tm) \
  do{ \
    LARGE_INTEGER time1, time2; \
    double z, span; \
    int n; \
    \
    QueryPerformanceCounter( &time1 ); \
    for( n=0,z=0; n<N; n++, z+=y) (f)(z); \
    QueryPerformanceCounter( &time2 ); \
    \
    time2.QuadPart -= time1.QuadPart; \
    span = (double) time2.QuadPart / freq.QuadPart; \
    \
    if( (tm)[SINMAX] < span ) (tm)[SINMAX] = span; \
    if( (tm)[SINMIN] == 0 || (tm)[SINMIN] > span ) (tm)[SINMIN] = span; \
    (tm)[SINAVE] += span; \
  } while(0)

#define PRITIME(tm,fn) \
  printf( "%s time: %.2f %.2f %.2f ms\n", (fn), (tm)[SINMIN]*1000., (tm)[SINMAX]*1000., (tm)[SINAVE] / (double) M * 1000.);

#define SINCHECK

void main(void)
{
  int m;
  double y;
  LARGE_INTEGER freq;
  double ts[SINLAST], ty[SINLAST], ty2[SINLAST];

  y = PI / (double) N;
  QueryPerformanceFrequency(&freq);
  INITIME( ts );
  INITIME( ty );
  INITIME( ty2 );
  initTables();

#ifdef SINCHECK
  {
    int n; double z;
    for( n=0,z=PI-y; n < N; n++, z-=y)
    {
      double m = mysin(z), m2 = mysin2(z), s = sin(z);
      if( fabs( (s-m) ) > 8e-4 ) printf( "Oops(mysin)... z=%g s=%g m=%g err=%g\n", z, s, m, fabs( (s-m) ));
      if( fabs( (s-m2) ) > 3e-7 ) printf( "Oops(mysin2)... z=%g s=%g m=%g err=%g\n", z, s, m2, fabs( (s-m2) ));
    }
  }
#endif

  for( m = 0; m < M; m++)
  {
    GETTIME( mysin, ty);
    GETTIME( mysin2, ty2);
    GETTIME( sin, ts);
  }

  PRITIME( ts, "sin");
  PRITIME( ty, "mysin");
  PRITIME( ty2, "mysin2");
}


Время получается такое:
Цитата

sin time: 88.84 97.85 92.51 ms
mysin time: 52.15 59.52 54.53 ms
mysin2 time: 94.72 105.79 99.33 ms

но, как выяснилось, на него нельзя положиться)))

Это сообщение отредактировал(а) feodorv - 6.2.2012, 21:08


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
feodorv
Дата 6.2.2012, 21:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Вот результаты LWS: http://liveworkspace.org/code/e981bae92390...f769efa0cac0587

Цитата
sin time: 40.000000 50.000000 43.600000 ms
mysin time: 20.000000 30.000000 23.300000 ms
mysin2 time: 20.000000 40.000000 27.000000 ms


По уму нужно сгенерировать таблицы tableSin etc, а не вычислять на ходу.
Рабочий отрезок 0<=z<PI, следовательно, нужны дополнительные манипуляции с аргументом, чтобы охватить всю числовую прямую, что также займёт время.



Если поиграться со значением константы MAX_ANGLE, то в конце концов можно достигнуть желаемой точности (при MAX_ANGLE=256*1024): http://liveworkspace.org/code/676649223321...7fbdf4b095fb2b6
Цитата

Max error: mysin=1.19834e-05 mysin2=7.18012e-11
sin time: 40.000000 60.000000 44.200000 ms
mysin time: 10.000000 30.000000 22.200000 ms
mysin2 time: 20.000000 40.000000 25.600000 ms


Это сообщение отредактировал(а) feodorv - 6.2.2012, 21:39


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Staskot
Дата 6.2.2012, 22:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



на моей VS 2010 отказывается почему-то показывать время) по нулям показывает)
PM MAIL   Вверх
feodorv
Дата 6.2.2012, 23:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(Staskot @  6.2.2012,  22:58 Найти цитируемый пост)
на моей VS 2010 отказывается почему-то показывать время) по нулям показывает) 

Какой вариант используется? С LWS?


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Staskot
Дата 6.2.2012, 23:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



Цитата(feodorv @  6.2.2012,  23:08 Найти цитируемый пост)
Какой вариант используется? С LWS? 

да с LWS) через дебаг работает) а через релайз нет)
PM MAIL   Вверх
Staskot
Дата 6.2.2012, 23:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



проблема решилась отключением оптимизации) вроде всё заработало) то что я её отключил сильно на что-нибудь повлияет?)
PM MAIL   Вверх
volatile
Дата 6.2.2012, 23:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Ну да все привально, 
Цитата(volatile @  3.2.2012,  23:48 Найти цитируемый пост)
Единственно, где есть какая-то надежда обогнать math.h,  это табличный синус.

а если его обрамить необходимыми проверками на выход из диапазона.
(кстати вы не пробовали синус отрицательного угла вычислить по вашей таблице  smile)
то выигрыш будет совсем ничтожным. Это притом что для таблицы в 3600 даблов, достигается точность
Цитата(borisbn @  6.2.2012,  16:31 Найти цитируемый пост)
delta is 0.000555748
т.е фактически 3 знака.
значит для 10 знаков точности понадобится таблица в 36000000000 даблов smile 

Цитата(feodorv @  6.2.2012,  23:08 Найти цитируемый пост)
Какой вариант используется? С LWS? 

LWS компилит в дебаговом режиме, если не о шибаюсь, так что проверять там быстродействие не стоит.

Добавлено через 3 минуты и 28 секунд
Цитата(Staskot @  6.2.2012,  23:51 Найти цитируемый пост)
проблема решилась отключением оптимизации) вроде всё заработало) то что я её отключил сильно на что-нибудь повлияет?) 

Можно и еще замедлить стандартный синус.
напишите обертку для него, тогда точно его обгоните  smile 
PM MAIL   Вверх
feodorv
Дата 7.2.2012, 00:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(feodorv @  6.2.2012,  21:03 Найти цитируемый пост)
Рабочий отрезок 0<=z<PI, следовательно, нужны дополнительные манипуляции с аргументом, чтобы охватить всю числовую прямую, что также займёт время.

Цитата(volatile @  6.2.2012,  23:52 Найти цитируемый пост)
а если его обрамить необходимыми проверками на выход из диапазона.

Цитата(volatile @  6.2.2012,  23:52 Найти цитируемый пост)
кстати вы не пробовали синус отрицательного угла вычислить по вашей таблице 

Вот-вот smile 

Цитата(volatile @  6.2.2012,  23:52 Найти цитируемый пост)
Можно и еще замедлить стандартный синус.

Вариант!!!


Цитата(Staskot @  6.2.2012,  23:51 Найти цитируемый пост)
то что я её отключил сильно на что-нибудь повлияет?) 

Да, стоит переписать программу так, чтобы получаемые значения как-то использовались, а то, действительно, компилятор понимает, что они нафик не нужны, вот и не вычисляет...
На LWS используется clock() вместо QueryPerformanceCounter()(((

Цитата(Staskot @  6.2.2012,  23:51 Найти цитируемый пост)
вроде всё заработало)

Какие цифры получились?


Цитата(volatile @  6.2.2012,  23:52 Найти цитируемый пост)
значит для 10 знаков точности понадобится таблица в 36000000000 даблов 

По новому варианту хватает трёх таблиц по 256*1024 элементов)))

Это сообщение отредактировал(а) feodorv - 7.2.2012, 00:13


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Staskot
Дата 7.2.2012, 00:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет




Цитата(feodorv @  7.2.2012,  00:07 Найти цитируемый пост)
Какие цифры получились?

Вот что у меня получилось:
Max error: mysin=1.19834e-05 mysin2=7.18012e-11
sin time: 31.000000 50.000000 33.700000 ms
mysin time: 10.000000 17.000000 11.480000 ms
mysin2 time: 15.000000 28.000000 17.030000 ms

PM MAIL   Вверх
feodorv
Дата 7.2.2012, 00:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(Staskot @  7.2.2012,  00:19 Найти цитируемый пост)
Вот что у меня получилось:

Супер! Время меньше, ошибка правильная, осталось с диапазоном аргументов разобраться))))


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Staskot
Дата 7.2.2012, 00:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



Цитата(feodorv @  7.2.2012,  00:33 Найти цитируемый пост)
Супер! Время меньше, ошибка правильная, осталось с диапазоном аргументов разобраться)))) 

да всё разобрался с диапазоном) Спасибо большое)

Добавлено через 3 минуты и 26 секунд
А может кто нибудь поделиться ссылками как так же оптимизировать другие функции) ну например exp 
 smile 
PM MAIL   Вверх
feodorv
Дата 7.2.2012, 01:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(Staskot @  7.2.2012,  00:48 Найти цитируемый пост)
да всё разобрался с диапазоном)

Не поделишься рецептом?)))

Попробуй вот так с оптимизацией (сократил N с 1000000 до 100000))):
Код

#include <windows.h>
#include <math.h>

#define PI 3.14159265358
#define MAX_ANGLE (256*1024)

static double tableVal[MAX_ANGLE];
static double tableSin[MAX_ANGLE];
static double tableCos[MAX_ANGLE];

void initTables()
{
  int i;

  for( i = 0; i < MAX_ANGLE; i++)
  {
    tableVal[i] = (double) i / (double) MAX_ANGLE * PI;
    tableSin[i] = sin( tableVal[i] );
    tableCos[i] = cos( tableVal[i] );
  }
}

double mysin( double x )
{
  return tableSin[ (int) (x / PI * (double) MAX_ANGLE) ];
}

double mysin2( double x )
{
  register int i = (int) (x / PI * (double) MAX_ANGLE);
  return tableSin[i] + (x - tableVal[i]) * tableCos[i];
}

#define N 100000
#define M 100

enum
{
  SINMIN = 0,
  SINMAX,
  SINAVE,
  SINLAST
};

#define INITIME(tm) \
    (tm)[SINMAX] = (tm)[SINMIN] = (tm)[SINAVE] = 0

#define GETTIME(f,tm,r) \
  do{ \
    LARGE_INTEGER time1, time2; \
    double z, span; \
    int n; \
    \
    QueryPerformanceCounter( &time1 ); \
    for( n=0,z=0; n<N; n++, z+=y) (r)[n] = (f)(z); \
    QueryPerformanceCounter( &time2 ); \
    \
    time2.QuadPart -= time1.QuadPart; \
    span = (double) time2.QuadPart / freq.QuadPart; \
    \
    if( (tm)[SINMAX] < span ) (tm)[SINMAX] = span; \
    if( (tm)[SINMIN] == 0 || (tm)[SINMIN] > span ) (tm)[SINMIN] = span; \
    (tm)[SINAVE] += span; \
  } while(0)

#define PRITIME(tm,fn) \
  printf( "%s time: %.2f %.2f %.2f ms\n", (fn), (tm)[SINMIN]*1000., (tm)[SINMAX]*1000., (tm)[SINAVE] / (double) M * 1000.);

#define CHERROR(e,r) \
  do{ \
    int n; \
    for( n = 0; n < N; ++n) \
      if( fabs(rs[n]-(r)[n]) > (e) ) (e) = fabs(rs[n]-(r)[n]); \
  } while(0)

double rs[N], ry[N], ry2[N];

void main(void)
{
  int m;
  double y;
  LARGE_INTEGER freq;
  double ts[SINLAST], ty[SINLAST], ty2[SINLAST];
  double err, err2;

  y = PI / (double) N;
  QueryPerformanceFrequency(&freq);
  err = err2 = 0;
  INITIME( ts );
  INITIME( ty );
  INITIME( ty2 );
  initTables();

  for( m = 0; m < M; ++m)
  {
    GETTIME( mysin, ty, ry);
    GETTIME( mysin2, ty2, ry2);
    GETTIME( sin, ts, rs);
    CHERROR( err, ry);
    CHERROR( err2, ry2);
  }

  printf( "Max error: mysin=%g mysin2=%g\n", err, err2);
  PRITIME( ts, "sin");
  PRITIME( ty, "mysin");
  PRITIME( ty2, "mysin2");
}


Добавлено через 1 минуту и 18 секунд
Цитата(Staskot @  7.2.2012,  00:48 Найти цитируемый пост)
А может кто нибудь поделиться ссылками как так же оптимизировать другие функции) ну например exp 

The show must go on smile 


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Staskot
Дата 7.2.2012, 01:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



Цитата(feodorv @  7.2.2012,  01:02 Найти цитируемый пост)
Попробуй вот так с оптимизацией (сократил N с 1000000 до 100000))):

Время не сильно отличается от прошлой программы) Но зато работает с оптимизацией ) большое спасибо) пойду попробую exp написать)

Добавлено через 13 минут и 42 секунды
Цитата(feodorv @  7.2.2012,  01:02 Найти цитируемый пост)
Не поделишься рецептом?)))

ахаха с диапазоном приврал) реально проблемы с ним возникают) 
PM MAIL   Вверх
Staskot
Дата 14.2.2012, 11:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



Извиняюсь за некромантию) но все же интересно переписал код под косинус) но при точности в 8 знаков теряется выыгрыш в скорости у стандартного) чёт не соображу ни как)
Код

#include <math.h>
#include <time.h>
#include <stdio.h>
#include <conio.h>
#define PI 3.14159265358
#define MAX_ANGLE (128*1024)

static double tableVal[MAX_ANGLE];
static double tableSin[MAX_ANGLE];
static double tableCos[MAX_ANGLE];

void initTables()
{
  int i;

  for( i = 0; i < MAX_ANGLE; i++)
  {
    tableVal[i] = (double) i / (double) MAX_ANGLE * PI;
    tableSin[i] = sin( tableVal[i] );
    tableCos[i] = cos( tableVal[i] );
  }
}

double mycos( double x )
{
  return tableCos[(int) (x / PI * (double) MAX_ANGLE)];
}

double mycos2( double x )
{
  register int i = (int) (x / PI * (double) MAX_ANGLE);
  return tableCos[i] + (x - tableVal[i]) * tableSin[i];
}

#define N 1000000
#define M 100

enum
{
  COSMIN = 0,
  COSMAX,
  COSAVE,
  COSLAST
};

#define INITIME(tm) \
    (tm)[COSMAX] = (tm)[COSMIN] = (tm)[COSAVE] = 0

#define GETTIME(f,tm) \
  do{ \
    double time1, time2; \
    double z, span; \
    int n; \
    \
    time1 = (double) clock(); \
    for( n=0,z=0; n<N; n++, z+=y) span = (f)(z); \
    time2 = (double) clock(); \
    \
    span = (time2 - time1) / CLOCKS_PER_SEC; \
    \
    if( (tm)[COSMAX] < span ) (tm)[COSMAX] = span; \
    if( (tm)[COSMIN] == 0 || (tm)[COSMIN] > span ) (tm)[COSMIN] = span; \
    (tm)[COSAVE] += span; \
  } while(0)

#define PRITIME(tm,fn) \
  printf( "%s time: %f %f %f ms\n", (fn), (tm)[COSMIN]*1000., (tm)[COSMAX]*1000., (tm)[COSAVE] / (double) M * 1000.);

#define SINCHECK

int main(void)
{
  int m;
  double y;
  double ts[COSLAST], ty[COSLAST], ty2[COSLAST];

  y = PI / (double) N;
  
  INITIME( ts );
  INITIME( ty );
  INITIME( ty2 );
  initTables();

#ifdef SINCHECK
  {
    int n; double z, e = 0., e2 = 0.;
    for( n=0,z=PI-y; n < N; n++, z-=y)
    {
      double m = mycos(z), m2 = mycos2(z), s = cos(z);
      if( fabs(s-m) > e ) e = fabs(s-m);
      if( fabs(s-m2) > e2 ) e2 = fabs(s-m2);
    }
    printf( "Max error: mycos=%g mycos2=%g\n", e, e2);
  }
#endif

  for( m = 0; m < M; m++)
  {
    GETTIME( mycos, ty);
    GETTIME( mycos2, ty2);
    GETTIME( cos, ts);
   
  }
  PRITIME( ts, "cos");
  PRITIME( ty, "mycos");
  PRITIME( ty2, "mycos2");
  getch();
  return 0;
}

PM MAIL   Вверх
feodorv
Дата 14.2.2012, 12:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(Staskot @  14.2.2012,  11:25 Найти цитируемый пост)
переписал код под косинус) но при точности в 8 знаков

Какие 8 знаков??? Вы с тригонометрией знакомы???

Цитата(Staskot @  14.2.2012,  11:25 Найти цитируемый пост)
  return tableCos[i] + (x - tableVal[i]) * tableSin[i];

Для cos - совершенно неправильная конструкция(((

Цитата(Staskot @  14.2.2012,  11:25 Найти цитируемый пост)
теряется выыгрыш в скорости у стандартного)

Даже в таком неверном варианте (ошибка mycos2 больше ошибки mycos!!!) считается быстрее (чуть-чуть).

В любом случае, держать в памяти от 3 до 6 мег таблиц - это безумие. Задача была интересна принципиально, но как прикладной вариант никуда не годится.


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Staskot
Дата 14.2.2012, 23:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



Цитата(feodorv @  14.2.2012,  12:19 Найти цитируемый пост)
Для cos - совершенно неправильная конструкция(((

а какая дожна быть формула?
PM MAIL   Вверх
feodorv
Дата 15.2.2012, 17:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(Staskot @  14.2.2012,  23:11 Найти цитируемый пост)
а какая дожна быть формула? 

Предлагаю вывести её самостоятельно  smile 
Намёк здесь)))


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Staskot
Дата 15.2.2012, 23:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 3.2.2012

Репутация: нет
Всего: нет



Цитата(feodorv @  15.2.2012,  17:48 Найти цитируемый пост)
Намёк здесь))) 

ну дык там же просто заменить + на - и все)

Добавлено через 2 минуты и 58 секунд
Цитата

cos (x + dx) = cos x · cos dx − sin x · sin dx

вот эта формула для косинуса)
Цитата(Staskot @  15.2.2012,  23:07 Найти цитируемый пост)
ну дык там же просто заменить + на - и все) 

ну эт у меня в коде)
PM MAIL   Вверх
feodorv
Дата 16.2.2012, 01:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(Staskot @  15.2.2012,  23:07 Найти цитируемый пост)
ну дык там же просто заменить + на - и все)

 smile 

Цитата(Staskot @  15.2.2012,  23:07 Найти цитируемый пост)
ну эт у меня в коде) 

В том, который приведён, стоит плюс smile 


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1222 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.