begin process at 2008 07 19 16:35:32
1 212 905 membres
227 nouveaux aujourd'hui
14 165 membres club

Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum.
Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

MEILLEURE MÉTHODE POUR CALCULER UN PUISSANCE


Information sur la source

Catégorie :Astuces Classé sous : exponentiation, extra, rapide Niveau : Initié Date de création : 19/11/2007 Date de mise à jour : 19/11/2007 18:44:46 Vu : 2 878

Note :
Aucune note

Commentaire sur cette source (7)
Ajouter un commentaire et/ou une note


Description

la méthode la plus naive pour calculer par ex:
x^15 = x*...*x(14 operations)
----------
mieux:
x * x = x2
x2 * x2 = x4
x4 * x4 = x8
x4 * x8 = x12
x12 * x2 = x14
x14 * x = x15(6 operations)
----------
n × n = n2
n2 × n = n3
n3 × n3 = n6
n6 × n6 = n12
n12 × n3 = n15
(5 operations)
ce programme donne les enchainements possible pour la plus rapide
méthode de calculer la puissance :)

Source

  • #include<iostream>
  • #include<set>
  • #include<queue>
  • #include<vector>
  • #define MAX 200
  • using namespace std;
  • int operations[MAX + 1] = {0};
  • // A tree struct
  • struct Tree
  • {
  • int Key, Level;
  • Tree * Parent;
  • vector<Tree* > children;
  • Tree(int Key, Tree* Parent)
  • {
  • this->Key = Key;
  • this->Parent = Parent;
  • if(Parent != NULL)
  • this->Level = Parent->Level + 1;
  • else
  • this->Level = 0;
  • }
  • };
  • // testing if all nodes are all computed
  • bool AllComputed()
  • {
  • for(int k = 1;k <= MAX;k++)
  • if(!operations[k])
  • return false;
  • return true;
  • }
  • // building tree with a given node and a range limit
  • void stacking(int n,Tree * T)
  • {
  • queue<Tree*> Q;
  • // using algorithm to parse a tree by levels
  • Q.push(T);
  • while (!Q.empty() && !AllComputed())
  • {
  • Tree * X = Q.front();
  • Q.pop();
  • Tree * Iterator = X;
  • int Value = X->Key;
  • //process node X
  • while(Iterator != NULL)
  • {
  • int TmpValue = Iterator->Key + Value;
  • if((!operations[TmpValue]|| operations[TmpValue]
  • == X->Level + 1)&& TmpValue <= n)
  • {
  • operations[TmpValue] = X->Level + 1;
  • (X->children).push_back(new Tree(TmpValue,X));
  • }
  • Iterator = Iterator->Parent;
  • }
  • int L = (int)(X->children).size();
  • for (int i = 0;i < L;++i)
  • {
  • Q.push((X->children)[i]);
  • }
  • }
  • }
  • void search(int k,Tree * T)
  • {
  • if(T->Key == k)
  • {
  • Tree * Iter = T;
  • set<int> S;
  • while (T != NULL)
  • {
  • S.insert(T->Key);
  • T = T->Parent;
  • }
  • for(set<int>::iterator iter = S.begin();;)
  • {
  • cout << *iter;
  • ++iter;
  • if(iter != S.end())
  • cout << "->";
  • else
  • {
  • cout << endl;
  • break;
  • }
  • }
  • }
  • else
  • {
  • vector<Tree *> v = T->children;
  • int L = (int)v.size();
  • for(int i = 0;i < L;++i)
  • search(k,v[i]);
  • }
  • }
  • int main()
  • {
  • Tree * T = new Tree(1,NULL);
  • stacking(MAX,T);
  • int key;
  • cout << "if you want to know how to obtain minimum number of operations :" << endl;
  • cout << "enter a positive number or (0) to quit" << endl;
  • cin >> key;
  • while(key)
  • {
  • cout << operations[key] << endl;
  • search(key,T);
  • cin >> key;
  • }
  • return 0;
  • }
#include<iostream>
#include<set>
#include<queue>
#include<vector>
#define MAX 200
using namespace std;

int operations[MAX + 1] = {0};

// A tree struct
struct Tree
{
	int Key, Level;
	Tree * Parent;
	vector<Tree* > children;
	Tree(int Key, Tree* Parent)
	{
		this->Key = Key;
		this->Parent = Parent;
		if(Parent != NULL)
			this->Level = Parent->Level + 1;
		else
			this->Level = 0;	

	}
};
// testing if all nodes are all computed
bool AllComputed()
{
	for(int k = 1;k <= MAX;k++)
		if(!operations[k])
			return false;
	return true;
}
// building tree with a given node and a range limit
void stacking(int n,Tree * T)
{
	queue<Tree*> Q;
	// using algorithm to parse a tree by levels
	Q.push(T);
	while (!Q.empty() && !AllComputed())
	{
		Tree * X = Q.front();
		Q.pop();
		Tree * Iterator = X;
		int Value = X->Key;
		//process node X
		while(Iterator != NULL)
		{
			int TmpValue = Iterator->Key + Value;
			if((!operations[TmpValue]|| operations[TmpValue] 
			== X->Level + 1)&& TmpValue <= n)
			{
				operations[TmpValue] = X->Level + 1;
				(X->children).push_back(new Tree(TmpValue,X));

			}
			Iterator = Iterator->Parent;
		}
		int L = (int)(X->children).size();
		for (int i = 0;i < L;++i)
		{
			Q.push((X->children)[i]);
		}

	}
}

void search(int k,Tree * T)
{
	if(T->Key == k)
	{
		Tree * Iter = T;
		set<int> S;
		while (T != NULL)
		{
			S.insert(T->Key);
			T = T->Parent;
		}
		for(set<int>::iterator iter = S.begin();;)
		{
			cout << *iter;
			++iter;
			if(iter != S.end())
				cout << "->";
			else
			{
				cout << endl;
				break;
			}

		}
	}
	else
	{
		vector<Tree *> v = T->children;
		int L = (int)v.size();
		for(int i = 0;i < L;++i)
			search(k,v[i]);

	}
}

int main()
{
	Tree * T = new Tree(1,NULL);
	stacking(MAX,T);

	int key;
	cout << "if you want to know how to obtain minimum number of operations :" << endl;
	cout << "enter a positive number or (0) to quit" << endl;

	cin >> key;
	while(key)
	{
		cout << operations[key] << endl;
		search(key,T);
		cin >> key;
	}

	return 0;
}
19 novembre 2007 18:44:46 :
prochainement mise à jour
  • signaler à un administrateur
    Commentaire de Cyberboy2054 le 19/11/2007 20:39:03

    Rigolo, mais au final tu ne fais pas beaucoup plus d'opérations que ce qu'il y avait au départ ? :p
    (oui je sais c'etait pas le but du programme)
    Juste une question, c'est une recherche en largeur ou en profondeur que tu fais ? j'ai jamais trop saisi la différence en fait.
    La ce que je vois, c'est que tu prends toutes les feuilles de ton arbre, et que tu en génère les successeurs (en virant les cas incompatibles/ceux qui ne resoudront jamais le probleme). Donc je dirais en profondeur. La largeur ce serait générer tous les successeurs d'un 'etage' en quelque sorte, puis pour tous les successeurs ainsi que ceux apparus générer les successeurs ...
    Concrètement, quelle est la différence entre les 2 algorithmes ? (en termes de temps et de mémoire)

  • signaler à un administrateur
    Commentaire de acx01b le 20/11/2007 12:32:56

    salut je n'ai pas vraiment regardé ton code mais qu'est-ce qui te dérange dans un code de ce type ???

    #define SUPERPRINTF(X) printf(#X "= %d\n", X)

    int puis(int a, unsigned int b) {
    int l,i,x,r;
    l = sizeof(unsigned int)*8-1;
    while(!(b & (1<<l)) && l >= 0) l--;
    x = a;
    r = 1;
    for (i = 0; i <= l; i++) {
    if (b & (1<<i)) r *= x;
    x *= x;
    }
    return r;
    }

    int main() {
    SUPERPRINTF(puis(2,13));
    }

  • signaler à un administrateur
    Commentaire de elkasimi2007 le 20/11/2007 12:48:32

    salut,
    d'abord on fait une recherche en profondeur pour trouver
    toutes les operations minimum
    ensuite on cherche à trouver la suite des multiplication
    possible on fait une recherche en largeur car le nombre de
    multiplication augmente de niveau en niveau.

    Pour ACX01B je n'ai pas bien saisi ce que tu veut dire : tu veux dire que je dois utiliser des fonctions au lieu de blocs d'instructions ou que j'utilise des instructions complexe pour rien faire??

  • signaler à un administrateur
    Commentaire de acx01b le 20/11/2007 13:32:21

    salut

    ce que j'ai mis comme code c'est le code utilisé habituellement pour calculer une puissance entière

    pour x^15 il fait

    x2 = x*x
    r = x*x2
    x4 = x2*x2
    r = r * x4
    x8 = x4*x4
    r = r * x8
    --> 6 opérations, mais il n'utilise que 2 temporaires et là il y a une différence je pense, donc pourquoi ta façon est-elle meilleure (c'est ça que je n'ai pas étudié comme problème mais je suppose que toi oui) ?

  • signaler à un administrateur
    Commentaire de elkasimi2007 le 20/11/2007 14:46:43

    salut
    généralement ma méthode est utilisé pour un operateur
    * qlq par exemple:
    object X;
    étant donné operateur * assez compliqué, on s'interressera
    plutot à minimiser le nombre d'appel à l'operateur que minimiser le nombre de cases mémoire alouées.
    c'est vrai pour le cas d'un operateur simple * pour les entiers ça parait inutile.

    excuse moi,car j'ai pas eu le temps de déchiffrer les
    << ,le sizeof et les ! pour comprendre le but de ton code :)

  • signaler à un administrateur
    Commentaire de vecchio56 le 20/11/2007 23:14:37 administrateur CS

    Ce qui est intéressant c'est de savoir laquelle de ces solutions est la plus rapide
    - Méthode naive
    - Méthode un peu meilleure
    - Recherche de la meilleure méthode et application de cette méthode

    Tu as une idée?

  • signaler à un administrateur
    Commentaire de Gwaihir le 15/02/2008 19:08:48

    Sa doit être possible de chronométrer nan ?
    on peut chronométrer les threads ?

Ajouter un commentaire

Pub



Appels d'offres

Dessins techniques
Budget : 60€
Animation Flash - Doma...
Budget : 370€
Application flash medi...
Budget : 1 000€

Snippets en rapport

CalendriCode

Juillet 2008
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

VS Express FR Gratuit !

VS Express en français et 100% gratuit !

Téléchargements

Logiciels à télécharger sur le même thème :

Boutique

Boutique de goodies CodeS-SourceS