Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1363 connectés 

 


 Mot :   Pseudo :  
 
 Page :   1  2
Page Suivante
Auteur Sujet :

Comment faire x^n ?

n°921139
Kalimuxo
!
Posté le 12-12-2004 à 19:13:44  profilanswer
 

Reprise du message précédent :
Personne n'a d'idée ?


---------------
/* Signature */
mood
Publicité
Posté le 12-12-2004 à 19:13:44  profilanswer
 

n°921140
Chronoklaz​m
Posté le 12-12-2004 à 19:16:58  profilanswer
 

La masturbation de neurones un dimanche soir, defois c'est pas evident :D

n°921210
Kalimuxo
!
Posté le 12-12-2004 à 20:13:45  profilanswer
 

c'est vrai ^^


---------------
/* Signature */
n°921419
pascal_
Posté le 12-12-2004 à 23:12:44  profilanswer
 

Kalimuxo a écrit :

Personne n'a d'idée ?


 
Le code de HelloWorld ne marche pas  :??: ?

n°921490
Chronoklaz​m
Posté le 13-12-2004 à 00:07:32  profilanswer
 

Kalimuxo a écrit :

Merci les gens ^^
 
Sinon autre problème :
 
a<--- a +1 OK
a<---- a + b MAL
a<----- a + 2 MAL
 
En gros faire x^n avec uniquement des manipulations avec des 1...


 
pascal_ => Same player play again !  :wahoo:


Message édité par Chronoklazm le 13-12-2004 à 00:08:23
n°921504
Ace17
Posté le 13-12-2004 à 00:25:57  profilanswer
 

Chronoklazm a écrit :

pascal_ => Same player plays again !  :wahoo:

 :ange:

n°921600
Lam's
Profil: bas.
Posté le 13-12-2004 à 09:45:21  profilanswer
 


C'est de l'impératif, pas de l'indicatif.
 
En anglais, l'impératif et le subjonctif s'expriment de la même façon que la forme infinitive, sans la préposition "to".
 
Donc, same player, play again. :p

n°921702
Ace17
Posté le 13-12-2004 à 12:11:17  profilanswer
 

Au temps pour moi, mais dans ce cas il faut mettre la virgule! :D

n°921713
Lam's
Profil: bas.
Posté le 13-12-2004 à 12:15:48  profilanswer
 

Pas forcément. C'était peut-être du subjonctif, comme dans:

God save the queen !


 
:D

n°922426
nick-nitro
dynamite
Posté le 14-12-2004 à 00:19:29  profilanswer
 

on peut utiliser des tablaux


---------------
boom
mood
Publicité
Posté le 14-12-2004 à 00:19:29  profilanswer
 

n°923450
gilou
Modérateur
Modzilla
Posté le 15-12-2004 à 00:27:47  profilanswer
 

Chronoklazm a écrit :

Code :
  1. int somme(int x, int n){
  2.    if (n == 1)
  3.        return x;
  4.    else
  5.        return x + somme(x, (n - 1));}
  6. int pow-iter(int x, int n, int k){
  7.  
  8.    if (n == 0) return 1;
  9.    else if (n == 1) return x;   
  10.    else if (n == 2) return k;
  11.    else return pow-iter(x, (n - 1), somme(x, k));}


 
Voilà quoi ! :kaola:
 
EDIT : C'est sur :jap: et bien c'est ce que je fais .

On pete la pile pour quelle valeur de n?
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°923765
chrisbk
-
Posté le 15-12-2004 à 12:55:33  profilanswer
 

gilou a écrit :

On pete la pile pour quelle valeur de n?
A+,


 
tu feras un overflow d'entier avant de peter la pile, je crois bien

n°924017
spokup
Posté le 15-12-2004 à 15:47:42  profilanswer
 

et l'algo d'exponentiation rapide ??
 
Pow(x, n);
 
result = x;
p = n;
 
while p
p pair (p%2==0)  -> result*=result; p>>=1;
p impair (p%n!=0) -> result*=x;  p--;
end loop
 
 
un truc du style ...

n°924019
spokup
Posté le 15-12-2004 à 15:48:47  profilanswer
 

arf sans utilisé les multiplication
 
excusez moi je suis hors sujet !

n°924039
Taz
bisounours-codeur
Posté le 15-12-2004 à 15:53:18  profilanswer
 

ça change rien, ta méthode est quand même logarithmique

n°924078
masklinn
í dag viðrar vel til loftárása
Posté le 15-12-2004 à 16:08:25  profilanswer
 

je comprend pas ce que le premier prog d'helloworld a de mal (sauf ptet une ou deux bornes dans les boucles), il fonctionne nickel pour x^n avec n > 0 et x >= 0
(et avec une valeur absolue bien placée il fonctionne même pour x < 0)
 
alors non il est pas optimisé ni rien, c'est une forme la plus développée possible (la plus simple au niveau conceptuel), mais ca fonctionne.
(en python ca donne:)

def pow(a,b):
    """ pow(a,b)-> result
        Compute and return a^b
        b must be > 0"""
    r = a
    for i in range(b-1):
            inter = r
            r = 0
            for j in range(abs(a)):
                    r+=inter
    return r


(me dites pas que ca fonctionne pas, j'arrive à calculer -564^1567 avec)
(c'est un peu long par contre)


Message édité par masklinn le 15-12-2004 à 16:13:46

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
n°924565
Chronoklaz​m
Posté le 15-12-2004 à 22:26:13  profilanswer
 

gilou a écrit :

On pete la pile pour quelle valeur de n?
A+,


 
Gilou je pige pas là, j'ai une recursivité terminale et ca devrai quand meme peter la pile ?


---------------
Scheme is a programmable programming language ! I heard it through the grapevine !
n°924599
gilou
Modérateur
Modzilla
Posté le 15-12-2004 à 22:53:33  profilanswer
 

Chronoklazm a écrit :

Gilou je pige pas là, j'ai une recursivité terminale et ca devrai quand meme peter la pile ?

non:

Code :
  1. int pow-iter(int x, int n, int k)
  2. {
  3.     ...
  4.     else return pow-iter(x, (n - 1), somme(x, k));
  5. }


 
Tu as une recursivite en n qui peut faire peter ta pile par depassement du nb d'appels recursifs possibles empiles.
C'est pas parce que tu commences par n et que tu decrois que le nb d'empilements d'appels a pow-iter ne fera pas peter ta pile pour une grande valeur de n (en fait ca se regle en parametrant au moment de la compilation (souvent parametrage par la valeur par defaut, donc non vu par le programmeur), et sous unix, ca peut se modifier apres coup).
 

chrisbk a écrit :

tu feras un overflow d'entier avant de peter la pile, je crois bien

probablement :)
 
A+,


Message édité par gilou le 15-12-2004 à 22:56:12

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°935811
dreameddea​th
Posté le 03-01-2005 à 15:40:34  profilanswer
 

Petit essai d'algo à chaud sans récursivité.

Code :
  1. int pow(int x,unsigned int n)
  2. {
  3. if(x==0) return 0; // j'ai un doute sur 0^0
  4. if(n==0) return 1;
  5. total=1;  //cas général
  6. if((n%2 == 1)&&(x<0)) total=-1; //seul cas ou le resultat sera négatif
  7. for(i=1;i<=n;++i)
  8. {
  9.     soustotal=total; //soustotal vaut x^(i-1)
  10.     for(j=1;j<=abs(x);++j)// on fait total=x*soustotal
  11.     {
  12.         total+=soustotal;
  13.     }
  14. }
  15. return total;
  16. }


Voilà j'espère que je n'ai pas fait d'erreur
 
Je suis ouvert à toute critique  :hello:  
 
++


Message édité par dreameddeath le 03-01-2005 à 16:01:03
n°936107
Chronoklaz​m
Posté le 03-01-2005 à 21:10:49  profilanswer
 

N'importe quoi puissance 0 ca rend 1 mais 0 puissance n'importe quoi sauf 0 rend 0 pourtant ta fonction pow(0,0) rend 0 ... pas bon.
 
Apres tu fait à la ligne 6 un modulo, je crois qu'on veut uniquement des additions de +1 ... donc pas bon.


---------------
Scheme is a programmable programming language ! I heard it through the grapevine !
n°936170
dreameddea​th
Posté le 03-01-2005 à 22:22:04  profilanswer
 

bah en fait il suffit donc d'inverser les deux premières lignes pour le pb du 0^0. Pour le coup du modulo je ne pensais pas aller jusque là mais  bon.
Voilà la nouvelle version qui n'a que des additions "+=" :)  

Code :
  1. int pow(int x,unsigned int n)
  2. {
  3.     if(n==0) return 1;
  4.     if(x==0) return 0;
  5.     total=1;  //cas général
  6.     tmp=n;
  7.     while (tmp>0) tmp+=-2; //boucle pour émuler le modulo 2 et pas de décalages car on a le droit qu'aux additions :)
  8.     if((tmp<0)&&(x<0)) total=-1; //seul cas ou le resultat sera négatif
  9.     for(i=1;i<=n;++i)
  10.     {
  11.         soustotal=total; //soustotal vaut x^(i-1)
  12.         for(j=1;j<=abs(x);++j)// on fait total=x*soustotal
  13.         {
  14.             total+=soustotal;
  15.         }
  16.     }
  17.     return total;
  18. }


 
Voilà, voilà

n°938258
Chronoklaz​m
Posté le 05-01-2005 à 18:15:00  profilanswer
 

gilou a écrit :

non:

Code :
  1. int pow-iter(int x, int n, int k)
  2. {
  3.     ...
  4.     else return pow-iter(x, (n - 1), somme(x, k));
  5. }


 
Tu as une recursivite en n qui peut faire peter ta pile par depassement du nb d'appels recursifs possibles empiles.
C'est pas parce que tu commences par n et que tu decrois que le nb d'empilements d'appels a pow-iter ne fera pas peter ta pile pour une grande valeur de n (en fait ca se regle en parametrant au moment de la compilation (souvent parametrage par la valeur par defaut, donc non vu par le programmeur), et sous unix, ca peut se modifier apres coup).
 
 probablement :)
 
A+,


 
Bon en fait je me suis renseigné et je pense que dans ce cas (ou on a une recursivité terminale) il n'y aura pas de depassement de pile car, à priori le compilateur gcc optimise la recursivité terminale (option de compilation -o9 je sais pas si c'est par defaut). Sinon j'ai appris que les recursivités croisés ne sont pas optimisé par gcc, je doute d'ailleurs qu'ils soient optimisables tout court.
Voila, donc pas de danger pour la pile :) (avec gcc en tout cas)  

n°996723
fra0
Posté le 01-03-2005 à 05:26:20  profilanswer
 

Code :
  1. // lol il y a des endroits plus appropriés pour utiliser la récursivité  
  2. int powpowpowpow(int a, unsigned b)
  3. {
  4.     if(!b--) return 1;
  5.     unsigned x=abs(a),n=b,i,j,k,l;
  6.     for(l=x ; i = x, k = 0, n-- ; l=k) while(i)
  7.     for(j = i & 1 ? l : 0 , i = j ? i - 1 : i >> 1 , l <<= !j ; j-- ; k++);
  8.     return b&1||a>0?l:-l;
  9. }

n°999975
maximew
Coffee and cigarettes and Cate
Posté le 03-03-2005 à 18:36:57  profilanswer
 

fra0 a écrit :

Code :
  1. // lol il y a des endroits plus appropriés pour utiliser la récursivité  
  2. int powpowpowpow(int a, unsigned b)
  3. {
  4.     if(!b--) return 1;
  5.     unsigned x=abs(a),n=b,i,j,k,l;
  6.     for(l=x ; i = x, k = 0, n-- ; l=k) while(i)
  7.     for(j = i & 1 ? l : 0 , i = j ? i - 1 : i >> 1 , l <<= !j ; j-- ; k++);
  8.     return b&1||a>0?l:-l;
  9. }



Magnifique!


---------------
Mon Flickr
n°1012093
matthieu_p​hpmv
Posté le 14-03-2005 à 14:43:15  profilanswer
 

fra0 a écrit :

Code :
  1. // lol il y a des endroits plus appropriés pour utiliser la récursivité  
  2. int powpowpowpow(int a, unsigned b)
  3. {
  4.     if(!b--) return 1;
  5.     unsigned x=abs(a),n=b,i,j,k,l;
  6.     for(l=x ; i = x, k = 0, n-- ; l=k) while(i)
  7.     for(j = i & 1 ? l : 0 , i = j ? i - 1 : i >> 1 , l <<= !j ; j-- ; k++);
  8.     return b&1||a>0?l:-l;
  9. }



 
 
maahh qu'est ce ? Comment telle prouesse est elle possible ?  :heink:   :love:  
as tu la théorie derrière ça ?


---------------
développeur de phpMyVisites mesure d'audience de sites Internet
n°1012432
Chronoklaz​m
Posté le 14-03-2005 à 18:47:30  profilanswer
 

matthieu_phpmv a écrit :

maahh qu'est ce ? Comment telle prouesse est elle possible ?  :heink:   :love:  
as tu la théorie derrière ça ?


 
On dirait du Brainfuck  :ouch:


---------------
Scheme is a programmable programming language ! I heard it through the grapevine !
n°1012452
IrmatDen
Posté le 14-03-2005 à 19:03:52  profilanswer
 

C'est clair que c'est totalement hallucinant.
>fra0 : c'est sympa de poster un algo qui déchire tout, mais peux-tu nous donner quelques explications stp ?

n°1012637
trictrac
Posté le 14-03-2005 à 22:31:37  profilanswer
 

+1, une petite explicationde comment t'es arrivé a ca ne serait pas de refu

n°1012721
dark86
Posté le 14-03-2005 à 23:22:05  profilanswer
 

heu, pourquoi je ne comprends aucune ligne du code de fra0??? :(

n°1012742
IrmatDen
Posté le 14-03-2005 à 23:28:58  profilanswer
 

parce que ses noms de variables sont hyper explicites? :/

n°1012748
dark86
Posté le 14-03-2005 à 23:31:19  profilanswer
 

et peut-etre aussi que j'avais jamais vu de "boucle" for avec rien deriere....

n°1012868
fra0
Posté le 15-03-2005 à 02:47:04  profilanswer
 


c'est ma façon de contourner la contrainte sur l'addition
 
TOTO=TOTO+TITI;  
 
s'écrit
 
TOTO+=TITI;  
 
ou encore
 
for(;TITI--;TOTO++);
 
après, c'est l'algorithme classique par multiplications successives.
A un moment, il faut multiplier A par B (donc aditionner A; B fois...)
Partant du principe qu'il vaut mieux additionner une fois 2A que deux fois A et à fortiori une fois 4A que quatre fois A...
je décime B, selon sa parité : si B est pair (B&1 == B%2 = faux), je le divise par deux et je multiplie A par 2 (grâce à des décalages (d/g) de 1) ; si B est impair (B&1 == B%2 = vrai), je lui enlève 1 et j'ajoute A au résultat (avec la troisième boucle qui ne se déroule que pour faire ce k+=j). Je recommence tant qu'il en reste dans B (multiplication égyptienne) je fixe le problème du signe à la fin grâce à l'exposant modifié.
 
Mais l'algo n'est pas optimal (en terme d'incréments) il suppose que 'b' est beaucoup plus petit que 'a' (dans a^b) et n'utilise pas vraiment l'exponentiation rapide.
 
C'était C3PO au milieu des Ewoks  :hello:

n°1012871
IrmatDen
Posté le 15-03-2005 à 03:54:39  profilanswer
 

De mon point de vue, c'est plus du R2D2 que C3PO... ;)

Citation :

Mais l'algo n'est pas optimal (en terme d'incréments) il suppose que 'b' est beaucoup plus petit que 'a' (dans a^b) et n'utilise pas vraiment l'exponentiation rapide.


Que veux tu dire par "b beaucoup plus petit que a" ?
 
Merci de tes eclaircissements...

n°1013487
fra0
Posté le 15-03-2005 à 15:52:21  profilanswer
 


J'ai essayé d'écrire l'aglo fonctionnel le plus court possible (pour des types de taille arbitraire) pas le plus rapide. Pour assurer le steak, j'ai fait quelques suppositions sur les valeurs de a et b.
 
Il y a des façons plus fines d'évaluer 2^2048 par exemple...
 
Ce que trouvais drôle, c'était de simuler la récursivité avec des structures de contrôle ('l' a deux cycles de vie et est utilisée comme une pile, 'j' contrôle l'élagage de l'arbre) sans branchements ni stockage superflu.

n°1013562
IrmatDen
Posté le 15-03-2005 à 16:40:21  profilanswer
 

ok. Merci de tes infos, c'est très instructif de voir d'autres façon de faire... Il me reste plus qu'à prévoir une petite pile d'aspirine pour décomposer et comprendre ton implémentation ;)

n°1013759
slvn
Posté le 15-03-2005 à 18:30:03  profilanswer
 

A mon avis, il faut tout sauf lire l'implementation.
c'est du "brain fuck" comme dit Chronoklaz, que seul son auteur peut comprendre :)
 
(Merci en tout cas, car au passage, je viens de decouvrir qu'on pouvait mettre plusieurs elements au milieu d'un "for()" )
 
Pour la comprehension de l'algo, il y a deux choses distinctes:
 
la multiplication x*y sans utiliser de multiplication :  
 
Il faut ecrire y comme somme de puissance de 2, et calculer chaque puissance de 2 avec un "left shit".
Si on pose y = a*2^0 + b*2^1 + c*2^2 + ...     avec a,b,c valant 1 ou 0.
alors x*y vaut  a(x<<0) + b(x<<1) + c(x<<2) + ...
 
Par exemple, x*10 == x<<1 + x<<3 puisque 10 vaut en héxa 0x1010.
 
Le deuxième algorithme est celui d'exponentionation rapide pour calculer x^y:
 
si on ecrit y en puissance de 2,  
y = a*2^0 + b*2^1 + c*2^2 + ...     avec a,b,c valant 1 ou 0. On peut réduire le nombre de multiplication nécessaire.
 
Par exemple: pour y == 15 == 0x1111
x^y = x * (x^2) * (x^4) * (x^8)    //4 multiplication
Mais il faut calculer les carrés:  
 x^2
(x^2)^2 == x^4
(x^4)^4 == x^8    
Soit 3 multiplications. Ce qui au final demande 7 multiplications au lieu des 15 initiales.
 
 
Pour calculer x^n sans aucune multiplication, on utilise d'abord l'exponentionation rapide pour reduire le nombre de multiplication, puis on faire chacune de multiplication avec des décalages :)
 
Voila, sinon comme le dit fra0, il y a différents petits trucs a checker.. Les overflows qui arrivent rapidement, et pour savoir si un nombre est une puissance de 2, on évaluer l'expression suivante:   "0 == x&(x-1)"
 
++
Sylvain


Message édité par slvn le 15-03-2005 à 18:30:38
n°1013964
IrmatDen
Posté le 15-03-2005 à 22:09:29  profilanswer
 

C'est mon tube d'aspi qui va être content :)
Merci de m'avoir précisé tout ça

n°1014022
papy_danon​e
Posté le 15-03-2005 à 23:15:32  profilanswer
 

faites des reductions logarithmiques. Au lieu d'incrementer que de 1 dans vos boucles à chaque passage, multipliez par 2 (en décalant les bits vers la gauche, comme ca pas de signe * :p ), la complexité de l'algo passe de n en log(n).

n°1014127
fra0
Posté le 16-03-2005 à 02:10:49  profilanswer
 

exemple

n°1018202
fra0
Posté le 19-03-2005 à 03:09:07  profilanswer
 

démonstration...

Code :
  1. /// pow (pour les types intégraux)
  2. /// sans addition (autre que +1/-1), ni multiplication,
  3. /// optimisée de haut (exponentiation rapide) en bas (addition binaire en temps constant) en passant presque par le milieu
  4. /// réponses en une fraction* de milliseconde (env 2µs sur un Athlon 1.4GHz dans le type natif).
  5. // ex : ALU <unsigned __int64> boulier;  
  6. #define MAXBITS (8*sizeof(uinteger))
  7. #define decimate(x,p) (x=p?x-1:x>>1)
  8. template <class uinteger> class ALU
  9. {
  10.   private:
  11.     inline bool _getBit(uinteger data,int n) { return data>>n&1; } //
  12.     inline void _setBit(uinteger &data, unsigned n, bool value) { data|=(uinteger)value<<n; } //
  13.   public:
  14.     uinteger add(uinteger a, uinteger b)
  15.     {
  16.         bool r1,r2,carry=false;
  17.         uinteger result=0;
  18.         for(unsigned bit=0;bit<MAXBITS;bit++)
  19.         {
  20.             r1=_getBit(a,bit);
  21.             r2=_getBit(b,bit);
  22.             _setBit(result,bit,r1==r2==carry); // r1^r2^carry
  23.             carry=r1?r2|carry:r2&carry; // r1&r2|r1&carry|r2&carry;
  24.         }
  25.         #ifdef CHECK
  26.             assert(carry==false && "sinon dépassement de capacité dans add" );
  27.         #endif
  28.         return result;
  29.     }
  30.     uinteger mult(uinteger a, uinteger b)
  31.     {
  32.         bool predicate;
  33.         uinteger maxi=max(a,b),result=0;
  34.         for(uinteger mini=min(b,a);mini>0;decimate(mini,predicate))
  35.         {
  36.             predicate=_getBit(mini,0);
  37.             if(predicate) result=add(result,maxi);
  38.             else
  39.             {
  40.                 #ifdef CHECK
  41.                     uinteger old=maxi;
  42.                 #endif
  43.                 maxi<<=1; // ou : maxi=add(maxi,maxi); au quel cas la fonction peut s'écrire comme pow...
  44.                 #ifdef CHECK
  45.                     assert(old<=maxi && "sinon dépassement de capacité dans mult" );
  46.                 #endif
  47.             }
  48.         }
  49.         return result;
  50.     }
  51.     uinteger pow(uinteger x, unsigned n)
  52.     {
  53.         bool predicate;
  54.         uinteger accu[2]={x,1};
  55.         for(unsigned rest=n;rest>0;decimate(rest,predicate))
  56.         {
  57.             predicate=_getBit(rest,0);
  58.             accu[predicate]=mult(accu[predicate],accu[0]);
  59.         }
  60.         return accu[1];
  61.     }
  62. };


 
edit :
 

  • suppression du stockage quadratique des masques binaires
  • rajout des tests de débordement


C'était pour quoi faire au fait ?


Message édité par fra0 le 19-03-2005 à 19:24:18
mood
Publicité
Posté le   profilanswer
 

 Page :   1  2
Page Suivante

Aller à :
Ajouter une réponse
 

Sujets relatifs
Plus de sujets relatifs à : Comment faire x^n ?


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR