Bonjour à tous,
J'ai écrit un algo qui multiplie deux nombres entiers non-signés et < 256 en se basant sur leur forme binaire. Il n'utilise que des opérations binaires comme le décalage de bits, etc.
Mon algo fonctionne (vous pouvez le lancer en ligne, cf. un peu plus bas), mais pas pour certains nombres. Quelques exemples de ce qu'il retourne :
-
0*0 = 0 donc OK
-
1*15 = 15 OK
-
88*2 = 176 OK
-
17*7 = 119 OK
-
255*255 = 32767 PAS BON
-
255*10 = 2046 PAS BON
-
15*15 = 127 PAS BON
-
1*255 = 255 OK
Vous pouvez le tester en ligne (notez qu'une archive des sources est disponible à la fin de ce message) : http://goo.gl/NZFuOT (compilez et exécutez, boutons en haut à gauche). (bug résolu)
Je ne vois vraiment pas d'où peut venir le problème. Le pire c'est que j'ai lancé mon débogueur, et je n'ai rien détecté d'anormal : mon programme semble faire exactement ce que je lui dis de faire et ne fait pas une action que je n'avais pas prévue.
EDIT : même les calculs simples (88*2) effectués sur le site juste au-dessus ne sont pas bons… mais sur mon ordi ils sont bel et bien OK.
Les types de variables seraient-ils mis en cause ?
Merci d'avance !
Voici mon code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | #include <stdio.h> void typeTwoIntegers(unsigned int*, unsigned int*); int getBitTheMostAtRight(unsigned int); const int number_of_bits_in_4_octets = sizeof(unsigned int)*8; // Un unsigned int est codé sur 4 octets donc possède 4*8 = 32bits int main(){ unsigned int op1 = 0, op2 = 0, original_op2_value; typeTwoIntegers(&op1, &op2); // Affecte les valeurs à op1 et à op2 original_op2_value = op2; // op2 sera amené à changer de valeur (à cause de décalages de bits) unsigned int array_temporary_products[sizeof(unsigned int)*8]; // Cet array contiendra les produits intermédiaires unsigned int op1_copy = 0; int i = 0; for (i = 0; i < number_of_bits_in_4_octets; i++) { int tmp_bit = getBitTheMostAtRight(op2); if (tmp_bit == 1) { // Si le bit le plus à droite de op2 est un 1, on inscrit op1 dans le tableau des produits intermédiaires sinon on écrit 0 // Il faut décaler les bits de ce produit intermédiaire (sauf ceux du premier : i=0 donc pas de décalage) (toujours afin de "simuler" un produit fait à la main) op1_copy = op1 << i; array_temporary_products[i] = op1_copy; } else { array_temporary_products[i] = 0; } op2 >>= 1; // On décale les bits d'op2 d'une position (ie. : d'un seul bit) ("simuler" un produit fait à la main) } // Maintenant qu'on a effectué les décalages nécessaires, on va pouvoir calculer le résultat final. unsigned int array_temporary_additions_and_final_result[sizeof(unsigned int)*8]; // Cet array contiendra les additions intermédiaires (cf. la suite du code) et, en guise de dernier élément, le résultat final. for (i = 0; i < number_of_bits_in_4_octets; i++) { if (i == 0) { // Première itération : la première addition intermédiaire est égale aux deux premiers produits intermédiaires additionnés entre eux array_temporary_additions_and_final_result[i] = (array_temporary_products[i] + array_temporary_products[i + 1]); } else { // Les autres additions intermédiaires sont égales à l'addition intermédiaire qui vient tout juste d'être effectuée + le produit intermédiaire suivant if (i + 1 < number_of_bits_in_4_octets) { // Il ne faut pas aller plus loin que la 32-ième case d'`array_temporary_products` (cf. commentaire suivant) array_temporary_additions_and_final_result[i] = (array_temporary_additions_and_final_result[i - 1] + array_temporary_products[i + 1]); } else { // (cf. commentaire précédent) Si pourtant c'est le cas, on affecte à la 32-ième case d'array_temporary_additions_and_final_result le résultat du produit array_temporary_additions_and_final_result[i] = (array_temporary_additions_and_final_result[i - 1]); } } } printf("Le produit de %u et %u est : %u", op1, original_op2_value, array_temporary_additions_and_final_result[i-1]); // i-1 car i = sizeof(unsigned int)*8 puisque situé après la boucle ! return 0; } int getBitTheMostAtRight(unsigned int val) { return val & 1; } void typeTwoIntegers(unsigned int* op1, unsigned int* op2) { do { printf("\n"); printf("Saisissez la première opérande : \n"); scanf("%u", op1); printf("Saisissez la dernière opérande : \n"); scanf("%u", op2); printf("\n"); } while (*op1 >= 256 || *op2 >= 256); } |
Archive des sources
-
Premier code source : http://goo.gl/SsCcgr
-
2-ième code source : http://goo.gl/RmL6tY (modifications par-rapport à la version précédente : code plus compact, lisible et optimisé niveau rapidité d'exécution)
-
Dernier code-source : http://goo.gl/NZFuOT (modifications par-rapport à la version précédente : correction du bug en procédant à des additions décimales au lieu de OU logiques, commentaires mis-à-jour)