COS ET SIN PLUS RAPIDE QUE MATH.H

coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 - 24 juil. 2004 à 13:44
BoboLaricot Messages postés 4 Date d'inscription vendredi 6 juin 2008 Statut Membre Dernière intervention 25 novembre 2008 - 16 oct. 2008 à 12:20
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/24821-cos-et-sin-plus-rapide-que-math-h

BoboLaricot Messages postés 4 Date d'inscription vendredi 6 juin 2008 Statut Membre Dernière intervention 25 novembre 2008
16 oct. 2008 à 12:20
Erreur de frappe : "return cosinus(x-PI/2)"
BoboLaricot Messages postés 4 Date d'inscription vendredi 6 juin 2008 Statut Membre Dernière intervention 25 novembre 2008
16 oct. 2008 à 12:20
J'ai lu ton code et je m'interroge,
Pourquoi stocker une table des sinus quand on sait que sin(x)=cos(x-PI/2) ?

A ta place je mettrai ça dans la fonction sinus :

float sinus(float)
{
return cosinus[x+PI/2]
}

Ca fait quand même une grosse économie de mémoire, non ?
ghino1987 Messages postés 4 Date d'inscription samedi 1 mars 2008 Statut Membre Dernière intervention 14 avril 2008
14 avril 2008 à 20:29
tu peux m aider a tracé la fonction sinus
BeLZeL Messages postés 110 Date d'inscription mardi 10 octobre 2000 Statut Membre Dernière intervention 20 décembre 2005
1 oct. 2005 à 21:03
En changeant quelques options de mon compilo (devcpp), j'ai des cos et des sin "classiques" plus rapides qu'avec ce code.

Pour DevCpp 4.9.9.2, avec mon Duron 1 GHz :
Editeur de liens : retirer les symboles de l'exe : [YES]
Génération du code : générer instructions : [i586]
Génération du code : utiliser les fonctions spécifiques : [MMX]
Optimisations du code : Toutes

En moyenne, les fonctions classiques sont 3 fois plus efficaces ! (170ms au lieu de 510ms)

Sans changer les options, les fonctions classiques (1500ms) sont 2 fois moins rapide que les fonctions modifiées (750ms).
zup2000 Messages postés 1 Date d'inscription vendredi 10 décembre 2004 Statut Membre Dernière intervention 14 décembre 2004
14 déc. 2004 à 01:58
je c je sui un peu en retar mé mieu fau tar que jamai!en faite si tu veu calculé un cosinus il te fau calculé son devellopement limité!!

pour la fonction cosinus son devellopement limité en 0 est :

1-(x²/2)+((x²)²/24).......
au plus tu ajoutera de therme au plus tu sera preci!voila jespere tavoir aidé!
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
1 oct. 2004 à 22:31
ma méthode ne marche pas car : segmentation fault...
pas assez de mémoire pour arriver a tout calculer...
expérimentation sur mon site
BeLZeL Messages postés 110 Date d'inscription mardi 10 octobre 2000 Statut Membre Dernière intervention 20 décembre 2005
1 oct. 2004 à 21:48
Attention à l'utilisation de rand() dans un "benchmark".

Avec 3 000 000 de valeurs, j'ai un facteur de x3 et avec 30 000 000, j'arrive à un facteur 9.
cs_djl Messages postés 3011 Date d'inscription jeudi 26 septembre 2002 Statut Membre Dernière intervention 27 novembre 2004 7
7 août 2004 à 18:54
et apres on obtient cos(n) n en degré dans l'intervalle [0, 90] c'est ca?
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
29 juil. 2004 à 12:56
en fait, on commence par faire ;

int long unsigned n[1000]
for (x=0 x<1000;x++){
for (y=0 y<1000;y++){
if (x*x+y*y==1000000){
n[x]=y;
}
int diametre=3141592;
on a obtenu un quart de cercle de rayon 1000 (1000 pour être précis)
ensuite, on cherche a combien doit être la distance entre deux points du cercle séparés d'un degré...

diametre=(diametre-diametre%360)/360;

ensuite, caclul basique :
int cos[90];
int sin[90];
x=0;
y=0;
j=0
for (i=0;i<1000;i++){
if ( (n[i]-y)*(n[i]-y)+(i-x)*(i-x)==diametre*diametre)
x=i;
y=n[i];
sin[j]=y;
cos[i]=x;
}
}
BlackGoddess Messages postés 338 Date d'inscription jeudi 22 août 2002 Statut Membre Dernière intervention 14 juin 2005
29 juil. 2004 à 10:00
l'avantage de décomposer le cosinus en opération simple peut permettre d'en faire un algo a la compilation aussi.

J'essayerais d'en faire une ebauche qd j'aurais un moment ...

djl -> oui, puis ca me paraissait bizarre que ce soit le role du préprocesseur d'évaluer des expressions en paramètres templates ...
et oui, je suis d'accord avec toi, du point de vue conceptuel on pourrait voir ca comme un préprocesseur c++
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
28 juil. 2004 à 22:11
bah oui, c'est plus rapide
cs_djl Messages postés 3011 Date d'inscription jeudi 26 septembre 2002 Statut Membre Dernière intervention 27 novembre 2004 7
28 juil. 2004 à 22:07
c'est meme mieux
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
28 juil. 2004 à 21:55
euh on peut s'arranger sans je crois, y a un algo ici pour ne pas s'en servir, et
if a=sqrt(b)
c'est pareil que
if (a*a=b)
cs_djl Messages postés 3011 Date d'inscription jeudi 26 septembre 2002 Statut Membre Dernière intervention 27 novembre 2004 7
28 juil. 2004 à 21:46
des que j'ai le temps je lee faiis, tu remarqueras que pour sqrt il faut inclure math.h
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
28 juil. 2004 à 21:44
moi aussi ça m'interese, en fait, j'ai pondu ça comme ça mais je ne l'ai jamais mis dans un de mes programme, donc, on est en compétition, on pourrais pas s'entre aider ?
ce serais plus simple
Moi, je vais commencer par expérimenter ce soir sur tibasic, puis demain sur pc, si j'y arrives...
cs_djl Messages postés 3011 Date d'inscription jeudi 26 septembre 2002 Statut Membre Dernière intervention 27 novembre 2004 7
28 juil. 2004 à 21:39
t'inquiete pas,a defaut de ne pas etre rapide, l'algo m'interesse pour les raison que tu as cités
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
28 juil. 2004 à 21:34
ça ne seras surement pas plus rapide qu'un tableau, mais ça te permetra de ne pas inclure math.h
ça te permet de faire vraiment ta fonction...
cs_djl Messages postés 3011 Date d'inscription jeudi 26 septembre 2002 Statut Membre Dernière intervention 27 novembre 2004 7
28 juil. 2004 à 21:32
t'avais raison, c'est bien le travail du compilateur, mais il fait quand meme le travail d'un preprocesseur

dans la logique ca pourait etre fais par un preprocesseur mais seul un compilateur permet de faire des controle statique (verification de code)

je suis pas sur que parler dans ce cas de preprocesseur c++ soit totalement faux mais je retir quand meme ce que j'ai dit ;)

coucou747 >merci, je vais voir avec ta solution, mais au niveau perf je sais pas si ca sera plus rapide qu'un tableau
BlackGoddess Messages postés 338 Date d'inscription jeudi 22 août 2002 Statut Membre Dernière intervention 14 juin 2005
28 juil. 2004 à 15:25
oui oui pour les maths je te fais confiance lol
c t a djl que je parlais :p
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
28 juil. 2004 à 14:27
tout dépends a qui tu parles lol
moi, je ne sais rien du préprocesseur, mai en math, je me débrouille
BlackGoddess Messages postés 338 Date d'inscription jeudi 22 août 2002 Statut Membre Dernière intervention 14 juin 2005
28 juil. 2004 à 11:06
mmh me semblait que le préprocesseur ne regardait que les lignes commencant par un (dièse)

as-tu un lien pour montrer ta 'certitude' ?
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
27 juil. 2004 à 23:10
Pour déterminer ton cosinus :

i=0;
for (x=-rayon,x<rayon, x++){
for (y=-rayon,y<rayon, x++){
/*formule permetant de calculer la longueur séparant l'origine de (x;y)*/
if (sqrt( y*y + x*x)=rayon){
pointx[i]=x;
point[i]=y;
i++;
}}}

ici, t'as tout les points du cercle, selon le rayon demandé, tu remplace le rayon par 1, et t'as cosinus en fonction du sinus, tu cherches un peu tu peux trouver une fonction permetant de faire ceci...
cs_djl Messages postés 3011 Date d'inscription jeudi 26 septembre 2002 Statut Membre Dernière intervention 27 novembre 2004 7
27 juil. 2004 à 18:50
oui , mon truc ne calcul pas le cos, mais la je vois pas comment faire

pour le
"oui, ca va faire bosser le preprocesseur c++ ;)
=> oulala :o"

désolé mais c'est le preprocesseur qui travaille, c'est une certitude, le compilo ne connais pas les templates et le code doit etre genere avant la compilation

les template sont un mechanisme de generation de code, quel rapport avec la compilation ?

a ton avis pourquoi on appel ca meta programmation ?
BlackGoddess Messages postés 338 Date d'inscription jeudi 22 août 2002 Statut Membre Dernière intervention 14 juin 2005
27 juil. 2004 à 15:44
oui, ca va faire bosser le preprocesseur c++ ;)
=> oulala :o
non ca fait bosser le compilo, pas le préprocesseur ...

l'exemple de djl se contente de déplier la boucle, pas le calcul du cosinus ...

il faudrait faire une opération comme :

template
int f()
{
return i;
}

int my_cos()
{
return f</* calcul du cosinus */>();
}

bon c pas terrible, c la 1ere solution qui me passe par la tete ...
ensuite, coupler cette solution a celle de djl pour obtenir un tableau de valeur entierement résolu a la compilation
cs_Xs Messages postés 368 Date d'inscription mercredi 14 novembre 2001 Statut Membre Dernière intervention 1 septembre 2008
27 juil. 2004 à 00:07
ah merci, c'est tout con mais j'y avais jamais pensé
cs_djl Messages postés 3011 Date d'inscription jeudi 26 septembre 2002 Statut Membre Dernière intervention 27 novembre 2004 7
26 juil. 2004 à 22:55
un truc du genre (toujours dans le but de faaire generer du code par le preprocessuer c++)

double v_cos[100];

template void init()
{
v_cos[N] = cos((double)N);
init<N-1>();
}

template<> void init<0>()
{
v_cos[0] = cos(0.0);
}

et l'appel de init<100>() genera le code completement deroulé

je te conseil le addison wesley sur les template, ya que ca
cs_Xs Messages postés 368 Date d'inscription mercredi 14 novembre 2001 Statut Membre Dernière intervention 1 septembre 2008
26 juil. 2004 à 22:37
BlackGoldness : peux tu donner un léger exemple de métaprog template ? Ca m'interesse grandement
cs_djl Messages postés 3011 Date d'inscription jeudi 26 septembre 2002 Statut Membre Dernière intervention 27 novembre 2004 7
26 juil. 2004 à 19:42
oui, ca va faire bosser le preprocesseur c++ ;)

et comme je l'ai dit, attention à la taille de l'exe
BlackGoddess Messages postés 338 Date d'inscription jeudi 22 août 2002 Statut Membre Dernière intervention 14 juin 2005
26 juil. 2004 à 14:41
peut etre sortir une version en c++ avec métaprogrammation template, pour que les valeurs précalculées soient résolues à la compilation plutot qu'a l'execution ? (attention au temps de compilation apres :p)
cs_Xs Messages postés 368 Date d'inscription mercredi 14 novembre 2001 Statut Membre Dernière intervention 1 septembre 2008
24 juil. 2004 à 20:15
bah c'est comme tu veux :D
J'avais totallement oublié fmod.

Mais bon, corrigez moi si j'ai tord, je pense pas que fmod soit plus rapide que ce que je présente : je ne crois pas qu'on puisse faire plus cours... (sauf peut etre avec de l'asm, hein brunews)

Donc en prennant ma méthode tu economises quelques cycles (genre ceux d'appel a fmod). :D
cs_djl Messages postés 3011 Date d'inscription jeudi 26 septembre 2002 Statut Membre Dernière intervention 27 novembre 2004 7
24 juil. 2004 à 17:50
ces icrementations n'ont rien d'hasardeuses, et c'est aussi rapide que fmod et j'ai bien conscience que c'est pas ce qu'il ya de plus efficace mais c'est le seul moyen que je connaisse, maintenant je vais essayer de voir avec la methode de Xs

sinon j'ai aussi bien preciser que c'etait 10 fois plus rapide dans l'intervalle et precalculer 20000 fois cos et sin c'est rien du moment qu'apres c'est rapide , ya que ca dans les jeux (dans certains, les 3/4 du temps de chargements c'est du precalcul)
si tu ve jeux te sort la version c++ qui fait l'initialisation à la compilation (par le preprocesseur) mais gar à la taille du prog

Xs > je vais essayer de mettre en place de cette maniere, en fait ce qu'il faut c'est une fonction qui calcul le modulo d'un reel plus rapide que fmod (ou alors j'utilise fmod ?)
garslouche Messages postés 583 Date d'inscription mardi 26 novembre 2002 Statut Membre Dernière intervention 29 mai 2015 1
24 juil. 2004 à 16:38
Xs > Je suis d'accord que cette méthode a des applications. Je voulais simplement dire que le titre est trompeur : il laisse supposer un algo plus efficace que celui de math.h. Et pour le calcul de l'indice du tableau je suis entièrement d'accord avec toi. Un calcul simple est bien plus efficace que ces incrémentations hasardeuses.
cs_Xs Messages postés 368 Date d'inscription mercredi 14 novembre 2001 Statut Membre Dernière intervention 1 septembre 2008
24 juil. 2004 à 15:50
Salut !

garslouche > c'est la méthode al plus rapide et la plus courante dans un jeu : on stock et on prend après. Les 20000 fois au départ tu t'en fiches : elles se font dans l'initialisation de ton jeu (et si c'est en thread, c'est encore plus invisible).

djl > j'ai lu ton code. Si je fais tr_cos(95851) je crois que je vais devoir patienter un bout de temps avant d'avoir l'abscisse curviligne de 95851 dans [-Pi;Pi].

Donc si tu veux calculer le sinus d'un réel "b" tel que b > 0 (sinon y'a une petite modif a faire) tu dois résoudre
b - k*Pi > -Pi/2 & b - k*PI < Pi/2 (la 1er equation est utile : ca n'induit pas b < 0 )

Je trouve que b/Pi -1/2 < k < b/Pi+1/2.
Donc pour le sinus de b (b > 0), tu calculs b/Pi+1/2 que tu castes en "int" (pour obtenir aisement la partie entiere) puis tu déduis k*Pi de b . Et la zoup, en 1 division, une addition, une soustraction, une multiplication, tu obtiens l'indice du tableau v_sin.

Pour le cos, tu résouds b-k*Pi < PI & b-k*pi > PI (peut etre qu'il y a une différence pour b < 0).

Bon, je peux me tromper, mais je suis sur qu'il y a NETTEMENT plus rapide que des incrémentations ( tu te rends compte ? au lieu d'un grand nombre d'inc tu fais juste v_sin[b-((int)(b/Pi+1/2)*Pi]
ca semble barbare mais c'est rapide)

cordialement
garslouche Messages postés 583 Date d'inscription mardi 26 novembre 2002 Statut Membre Dernière intervention 29 mai 2015 1
24 juil. 2004 à 15:15
Euh.... arrete moi si je me trompe mais j'ai decortiqué ton code et d'apres ce que jai compris c'est juste que tu calcules 20000 valeurs de cos que tu stockes dans un tableau une fois au début, et ensuite tu renvoies la valeur la plus proche ...
Je ne vois pas en quoi c'est plus rapide que math.h puisque tu commences par appeler 20000 fois la fonction cos de math.h !

Si tu veux savoir comment un ordi calcule un cos tu peux regarder ma source "math.h reprogrammé"
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
24 juil. 2004 à 13:44
bah moi ça va m'aider a comprendre comment fonctionne time.h.... lol j'ai regardé ton code, j'ai pas compris grand chose enfin bon, si ça marche...
tu pourrais détailler un peu ? expliquer pourquois ça marche ? En général, je suis plutot pas mauvais en math, mais dès que je vais sur ce site, je déprime... lol
Rejoignez-nous