Partage
  • Partager sur Facebook
  • Partager sur Twitter

Addition sans le signe "+"

    21 février 2020 à 10:28:33

    Bonjour, 

    je cherche une méthode pour réussir à faire une somme dans mon programme mais sans utilisé le signe "+" donc soit avec des manipulations de bits 

    Auriez vous une idée pour m'aider?

    -
    Edité par KylianJaeger1 21 février 2020 à 10:56:30

    • Partager sur Facebook
    • Partager sur Twitter
      21 février 2020 à 11:11:24

      KylianJaeger1 a écrit:

      donc soit avec des manipulations de bits ...

      ... soit quoi? Ta phrase n'est pas complète.

      De plus, une somme de quoi? Parce que décaler un entier d'un bit vers la gauche fait une somme: la somme du nombre avec lui-même. 

      -
      Edité par zoup 21 février 2020 à 11:13:32

      • Partager sur Facebook
      • Partager sur Twitter
        21 février 2020 à 12:31:16

        On dirait ce qu'il faut faire pour un de mes défis :) 

        A B N R
        0 0 0 0
        0 1 1 0
        1 0 1 0
        1 1 0 1

        N étant le digit (en binaire) et R la retenu de A+B.

        N = A xor B
        R = A and B

        la retenu se propage au bit suivant.

        On en déduit que :
        A+B = A xor B + (A and B)<<1

        Bon , il y a encore le signe '+' :( 
        C'est une écriture récursive :D 

        Je ne ferais pas la démo ici, mais A and B va toujours finir par valoir 0, et dans ce cas, on aura A+B = A xor B.

        Le pire des cas étant B=-1



        • Partager sur Facebook
        • Partager sur Twitter
          21 février 2020 à 14:37:22

          ok merci deja tu m'as aidé neuneutrinos,

          je vais etre un peu plus précis...

          je dois faire un affichage avec des leds et des switchs, on selectionne le nombre voulu en binaire avec les switchs 0 à 6 et on le valide avec le switch 7

          à la premiere selection notre chiffre apparait en clignottant, ensuite, quand on revient avec tous les switchs à zero on selectionne le deuxieme chiffre.

          à ce moment la les leds affichent le resultat de la somme des deux chiffres entré précedemment...

          ma contrainte etant de ne pas utiliser le signe "+" , (qu'avec des manipulations de bits)

          mon programme de base fonctionne il ne me reste plus qu'à rouver ma fonction additionneuse...

          voili voila

          • Partager sur Facebook
          • Partager sur Twitter
            21 février 2020 à 14:47:17

            Dans ce cas , méthode d'un additionneur complet (celle que j'ai exposé au dessus)

            A+B = A^B+(A&B)<<1
            Exemple en récursif ( peut se faire de manière itératif assez simpleement)

            #include <stdint.h>
            //si b= 0 alors a+b = a
            //sinon a+b = a^b + (a&b)<<1
            uint8_t adder(uint8_t a,uint8_t b)
            {
             return b?adder(a^b,(a&b)<<1):a;
            }


            Il ne reste qu'à stocker a et b et de mettre en sorti le résultat de l'addition ;) 

            • Partager sur Facebook
            • Partager sur Twitter
              21 février 2020 à 14:48:05

              nickel merci beaucoup juste question...

              tes deux points avant le a signifient quoi?

              -
              Edité par KylianJaeger1 21 février 2020 à 15:01:38

              • Partager sur Facebook
              • Partager sur Twitter
                21 février 2020 à 15:02:41

                KylianJaeger1 a écrit:

                Voila mon code si jamais vous avez des remarques....


                Je ne vois pas le code de la fonction additionneur

                PS: tout ton code a disparu d'ailleurs.

                "tes deux points avant le a signifient quoi?"

                C'est l'opérateur ternaire des langages C/C++. ca remplace un if ... else

                -
                Edité par zoup 21 février 2020 à 15:05:13

                • Partager sur Facebook
                • Partager sur Twitter
                  21 février 2020 à 15:38:28

                  c'est bon j'ai compris

                  merci a vous deux 

                  juste derniere question, ton additionneur marche lorsque les deux nombre entrés sont similaire, s'il ne l'es pas mes leds ne s'allument pas...

                  vous auriez une explication?

                  /* PROGRAMME Additionneur																										*
                  *                                                                         	*
                  * Lieu      : EPSIC                                    		       						*
                  * Auteur    : Kylian Jaeger										      									      *
                  * Date      : 13.02.2020                                 										*
                  *                                                                         	*
                  * Modifications                                                           	*
                  *   Auteur  : ....................                                        	*
                  *   Date    : ....................                                        	*
                  *   Raisons : ....................																					*
                  ****************************************************************************/
                  
                  
                  /****************************************************************************
                  * DESCRIPTION																*
                  * 																	        *
                  * 																	        *
                  ****************************************************************************/
                  
                  // Include
                  
                  // Les variables globales, librairies, prototype et les ports...
                  // ...sont définis dans le fichier header
                  
                  #include "additionneur.h"
                  
                  char nombre1 = 0;
                  int retenue;
                  int sortie;
                  int retenue1 = 0;
                  int xor1;
                  int and1;
                  int and2;
                  int sortie;
                  int index = 0;
                  int a;
                  int b;
                  
                  // Fonction principale
                  void main()
                  {
                  
                  	// Déclarations des variables locales
                  char etape = 0;
                  char nombre1 = 0;
                  char resultat1 = 0;
                  char nombre2 = 0;
                  char resultat = 0;
                  
                  
                      // Initialisations
                  	Init();
                  	
                  
                   	// Programme principal
                  	while(1)
                  	{
                  		
                  			switch (etape)
                  		{
                  			case 0:
                  							while(ESwitchs < 0x80)
                  							{
                  								SLeds = ALLUMES;
                  								Delay1ms (DELAI);
                  								SLeds = ETEINTES;
                  								Delay1ms (DELAI);
                  								etape = 1;
                  							}
                  			break;
                  							
                  			case 1:
                  						
                  							nombre1 = ESwitchs;
                  							nombre1 = nombre1 & 0x7F;
                  		
                  							while (ESwitchs != 0x00)
                  							{
                  								SLeds = nombre1;
                  								Delay1ms (DELAI);
                  								SLeds = ETEINTES;
                  								Delay1ms (DELAI);
                  								etape = 3;
                  							}
                  							resultat1 = nombre1;
                  			break;
                  						
                  			case 2:
                  							while(ESwitchs < 0x80)
                  							{
                  								SLeds = ALLUMES;
                  								Delay1ms (DELAI);
                  								SLeds = ETEINTES;
                  								Delay1ms (DELAI);
                  								etape = 3;
                  							}
                  			break;
                  					
                  			case 3:
                  			
                  						if ( ESwitchs >= 0x80)
                  						{
                  							nombre2 = ESwitchs;
                  							nombre2 = nombre2 & 0x7F;
                  							resultat = additionneur (resultat1, nombre2);
                  			
                  								while (ESwitchs != 0x00)
                  								{
                  									SLeds = resultat;
                  									Delay1ms (DELAI);
                  									SLeds = ETEINTES;
                  									Delay1ms (DELAI);
                  									etape = 0;
                  								}
                  						}
                  			break;
                  
                  		}
                  
                  
                  	}
                  
                  }
                  



                  -
                  Edité par KylianJaeger1 21 février 2020 à 16:08:18

                  • Partager sur Facebook
                  • Partager sur Twitter
                    21 février 2020 à 15:57:18

                    KylianJaeger1 a écrit:

                    juste derniere question, ton additionneur marche lorsque les deux nombre entrés sont similaire, s'il ne l'es pas mes leds ne s'allument pas...

                    vous auriez une explication?

                    Oui. L'erreur est ailleurs dans ton code, car la fonction d'addition est correcte. Mais comme toujours, sans code....
                    • Partager sur Facebook
                    • Partager sur Twitter

                    On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

                      21 février 2020 à 17:34:20

                      @zoup:
                      Décaler un nombre vers la gauche (et/ou droite) ne correspond pas du tout à une addition sur le plan électronique.
                      @neuneutrinos:
                      Tu essaies justement de simuler les fonctions électroniques logiques de base pour faire une addition? J'y ai pensé récemment.
                      Il faut tenir compte du carry précédent pour obtenir le carry suivant.
                      Notre collègue Fvirtman saurait sans doute nous dire comment faire.
                      Si a et b sont les bits, c le carry, r le résultat et C le nouveau carry:
                      a 0 0 0 0 1 1 1 1
                      b 0 0 1 1 0 0 1 1
                      c 0 1 0 1 0 1 0 1
                      -
                      r 0 1 1 0 1 0 0 1
                      C 0 0 0 1 0 1 1 1
                      Si je ne me suis pas trompé dans mes colonnes :)
                      • Partager sur Facebook
                      • Partager sur Twitter

                      Le Tout est souvent plus grand que la somme de ses parties.

                        21 février 2020 à 17:52:25

                        Re,-

                        Tu aurais dû créer une nouvelle réponse, pas modifier la précédente, mais bon.

                        Question: tu rentres comment dans ton case 2 ? Ligne 83, ne serait-ce pas etape=2 ? (mais je n'ai pas cherché à comprendre ton programme).

                        -
                        Edité par edgarjacobs 21 février 2020 à 18:04:55

                        • Partager sur Facebook
                        • Partager sur Twitter

                        On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

                          21 février 2020 à 18:12:42

                          PierrotLeFou a écrit:

                          @zoup:
                          Décaler un nombre vers la gauche (et/ou droite) ne correspond pas du tout à une addition sur le plan électronique.

                          Oui, je sais bien, je suis électronicien de formation. Je voulais juste dire que la question n'était pas suffisamment précise.

                          Un décalage à gauche multiplie par 2, donc additionne un nombre avec lui-même, ce qui répondait à la question tant qu'elle restait aussi vague.

                          PierrotLeFou a écrit:

                          Tu essaies justement de simuler les fonctions électroniques logiques de base pour faire une addition?

                          Oui, la formule est celle d'un "full adder". Ca marche donc pour l'addition de 2 bits. L'appel récursif permet de traiter des mots de taille quelconques.

                          • Partager sur Facebook
                          • Partager sur Twitter
                            21 février 2020 à 18:37:28

                            Qu'est ce que vous allez chercher comme complications.

                            A + B = A - (- B)

                            • Partager sur Facebook
                            • Partager sur Twitter
                              21 février 2020 à 18:44:22

                              @zoup:
                              Daccord, si tu es électronicien. J'ai des notions très basiques en électronique.
                              Comment je fais à chaque "étage" de l'additionneur en utilisant uniquement les fonctions logiques '^' '&' '|' et l'inverseur '~'?
                              J'ai en entrée les deux bits des nombre et le carry précédent et en sortie le bit résultant et le nouveau carry.
                              Tu part avec un carry de 0 et tu ignores le dernier carry de sortie (ou tu l'envoies dans l'overflow).
                              Si tu fais un ring counter, tu as un seul bit plus le carry que tu initialises à 1.
                              La logique devrait être plus simple.
                              • Partager sur Facebook
                              • Partager sur Twitter

                              Le Tout est souvent plus grand que la somme de ses parties.

                                22 février 2020 à 1:18:35

                                J'avoue avoir du mal à te suivre.

                                En tout cas, la solution de neuneutrinos est très futée.

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  22 février 2020 à 3:31:56

                                  @zoup:
                                  Ce à quoi je fais allusion est ce qui suit:
                                  https://fr.wikipedia.org/wiki/Additionneur
                                  Et voici le code mal foutu que j'ai codé. :)
                                  -
                                  #include <stdio.h>
                                  // Obtenir le digit suivant.
                                  int digit(int a, int b, int c) {
                                    return((a^b)^c);
                                  }
                                  // Retenue suivante.
                                  int carry(int a, int b, int c){
                                    return( (a&b) | (a&c) | (b&c) );
                                  }
                                  // Programme principal.
                                  int main(){
                                    for(int a=0; a<2; a++)
                                      for(int b=0; b<2; b++)
                                        for(int c=0;c<2;c++)
                                          printf("%d%d%d,%d,%d\n", a, b, c, digit(a, b, c), carry(a, b, c));
                                  return(0);
                                  }
                                  -
                                  Il n'y a que des fonctions logiques dans l'évaluation du digit et de la retenue suivants.

                                  -
                                  Edité par PierrotLeFou 22 février 2020 à 4:20:22

                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  Le Tout est souvent plus grand que la somme de ses parties.

                                    22 février 2020 à 17:30:15

                                    Le problème, c'est que tu ne traites pas l'addition d'entiers pour le moment. :)

                                    -
                                    Edité par zoup 22 février 2020 à 17:30:26

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      22 février 2020 à 18:56:27

                                      KylianJaeger1 a  écrit:
                                      «je dois faire un affichage avec des leds et des switchs».
                                      Ça veut dire quoi en fin de compte?
                                      Pour faire une addition en C, tu fais r = a + b, non?
                                      Suppose qu'on a deux tableaux représentant les bits de deux nombres affichés avec les LED.
                                      On a besoin (si nécessaire) d'un troisième tableau pour le résultat.
                                      Sinon, on choisit un des tableaux comme 'accumulateur' et on y place le résultat des additions successives.
                                      Si j'utilise mes fonctions 'digit()' et 'carry()'
                                      Je part des 'bits' les moins significatifs et je me déplace vers les bits les plus significatifs, je part avec un carry égal à 0.
                                      Je propage mon carry d'un bit à l'autre. J'aurai la somme en 'bits'.
                                      Je n'aurai qu'à afficher la somme dans les LED virtuels (ou réels).
                                      C'est une addition simulée en n'utilisant pas "d'addition".
                                      Chaque 'digit' est évalué avec deux circuits XOR (2-inputs XOR gate).
                                      Le carry est plus compliqué.
                                      Il requière 3 circuits 2-inputs AND gate et 1 circuit 3-inputs OR gate.
                                      C'est bien comme ça qu'on dit en électronique?
                                      • Partager sur Facebook
                                      • Partager sur Twitter

                                      Le Tout est souvent plus grand que la somme de ses parties.

                                        22 février 2020 à 21:40:41

                                        PierrotLeFou a écrit:

                                        Il requière 3 circuits 2-inputs AND gate et 1 circuit 3-inputs OR gate.
                                        C'est bien comme ça qu'on dit en électronique?

                                        Oui, c'est bien comme çà.

                                        Sur le fond, il serait peut-être intéressant de connaitre la raison de l'impossibilité d'utiliser l'opérateur +. 

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          23 février 2020 à 1:33:51

                                          D'après son code, il utilise un template généré par un IDE.
                                          Il parle de fonctions pour allumer ou éteindre des LED et des fonctions de délai.
                                          C'est comme s'il avait codé pour une petite machine comme un Arduino ou l'équivalent.
                                          Je n'ai pas compris où il obtenait la valeur de ses switch.
                                          Comme ça arrive trop souvant, l'auteur du sujet ne nous donne que peu de feedback après quelques messages ...
                                          • Partager sur Facebook
                                          • Partager sur Twitter

                                          Le Tout est souvent plus grand que la somme de ses parties.

                                            23 février 2020 à 15:23:58

                                            PierrotLeFou a écrit:

                                            Je n'ai pas compris où il obtenait la valeur de ses switch.
                                            Moi non plus. Du coup pas moyen de sortir de ses "while" vu que la variable ESwitchs n'est pas modifiée dans la boucle.

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              23 février 2020 à 16:25:54

                                              Bonjour,

                                              je me demandais est ce que c'est possible d'additionner c'est deux nombre à partir de l'équation logique de l'addition et de la répéter n bits dans une boucle while, ou par récursion. De même pour les retenus. C'est peut-être bête o_O

                                              -
                                              Edité par Kasewa 23 février 2020 à 16:26:16

                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                23 février 2020 à 17:13:43

                                                C'est ce que je suggérais à @zoup plus haut.
                                                Comme j'ai dit, tu as deux tableaux représentant tes deux nombres en bits.
                                                Ça peut être des tableaux de tout type "entier" (int, short ou char).
                                                Tu ne mets que '0' ou '1' dans chaque élément du tableau.
                                                Tu te fais une boucle du genre que tu veux (do {} while; while{} ou for(){} )
                                                Le "carry" (ou retenue) est une simple variable. Il vaut 0 au départ.
                                                Pour chaque paire de bits de tes tableaux, tu obtient le bit "somme" avec ma fonction digit() et le nouveau carry avec la fonction carry().
                                                Il faut juste que tu commences par les bits les moins significatifs.
                                                Ils peuvent être à l'indice 0 comme ça peut être à l'indice "maximum" -1.
                                                Tu affiches dans l'ordre inverse (soit en commençant par les bits les plus significatifs).
                                                • Partager sur Facebook
                                                • Partager sur Twitter

                                                Le Tout est souvent plus grand que la somme de ses parties.

                                                  24 février 2020 à 7:56:53

                                                  Merci,

                                                  j'ai résolu mon problème, j'ai utilisé la technique de neuneutrinos soit :

                                                  int additionneur (resultat1, nombre2)
                                                  {																													
                                                  	return resultat1^nombre2|(resultat1&nombre2)<<1;	
                                                  }


                                                  Tou marche parfaitement merci👌👌

                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    24 février 2020 à 8:45:50

                                                    Ca marche parfaitement, faut le dire vite :

                                                    d'après KylianJeager1 : 
                                                     1 + 3 = 2
                                                     1 + 7 = 6
                                                     2 + 6 = 4
                                                     2 + 7 = 5
                                                     3 + 1 = 2
                                                     3 + 5 = 6
                                                     3 + 6 = 5
                                                     3 + 7 = 6
                                                     5 + 3 = 6
                                                     5 + 7 = 10
                                                     6 + 2 = 4
                                                     6 + 3 = 5
                                                     7 + 1 = 6
                                                     7 + 2 = 5
                                                     7 + 3 = 6
                                                     7 + 5 = 10
                                                    


                                                    Programme pour trouver les contre-exemples :

                                                    #include <stdio.h>
                                                    
                                                    int additionneur (int resultat1, int nombre2)
                                                    {                                                                               
                                                       return resultat1^nombre2|(resultat1&nombre2)<<1; 
                                                    }
                                                    
                                                    int main() {
                                                      printf("d'après KylianJeager1 : \n");
                                                      for (int i = 0; i < 8; i++) {
                                                        for (int j = 0; j < 8 ; j++) {
                                                          int s = additionneur(i,j);
                                                          if (s != i+j) {
                                                    	printf(" %d + %d = %d\n", i, j, s);
                                                          }
                                                        }
                                                      }
                                                    }
                                                    

                                                    Y a un problème de fond, avec des opérations bit à bit, on ne peut pas simuler la propagation de retenue qui se produit dans une addition (le bit le plus à gauche du résultat dépend des bits les plus à droite).

                                                    -
                                                    Edité par michelbillaud 24 février 2020 à 8:49:31

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      24 février 2020 à 10:26:01

                                                      Je n'ai pas utilisé l'opérateur OR.

                                                      L'idée est que : A+B = (A^B) + (A&B)<<1
                                                      ça n'enlève pas l'addition directement, il faut boucler ou bien faire un appel récursif jusqu'à ce que B == 0

                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        24 février 2020 à 10:31:52

                                                        Oui, notre camarade a lu la formule de travers, sans voir l'appel récursif.

                                                        Enfin bon, ce que j'en dis : si on écrit une fonction qui est censé calculer un truc d'une façon biscornue, c'est bien de prévoir de tester qu'on obtient les bons résultats avant de crier victoire. Tester, tester, tester systématiquement.

                                                        Et là, on peut même se permettre un test exhaustif, parce qu'on sait calculer le même résultat d'une autre façon, et que sur 2 x 8 bits, ça fait jamais que 65000 cas de test, ce qu'un ordinateur fait très bien en une fraction de seconde. Automatiser les tests.

                                                        -
                                                        Edité par michelbillaud 24 février 2020 à 10:36:27

                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          24 février 2020 à 13:49:13

                                                          Et on ne sait toujours pas pourquoi il est nécessaire de contourner l'utilisation d'une bête addition avec l'opérateur +
                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            24 février 2020 à 14:43:27

                                                            En définitive, est-ce que le code de neuneutrinos fonctionne? Je n'ai pas vu de référence à la retenue qui se propage.
                                                            Je vais suivre le conseil de michelbillaud, je vais tester mon code de façon exhaustive.
                                                            • Partager sur Facebook
                                                            • Partager sur Twitter

                                                            Le Tout est souvent plus grand que la somme de ses parties.

                                                              24 février 2020 à 15:45:32

                                                              Non je pense qu'il peut utiliser l'opérateur + au vue de ce qu'il souhaite faire.
                                                              Au départ je pensais à une restriction supplémentaire pour le fun .

                                                              Et oui mon code fonctionne(il n'a pas repris mon code)

                                                              Pour la retenue qui se propage :

                                                              A+B = A^B + (A&B)<<1

                                                              Dans l'algorithme (et c'est le plus compliqué à montrer), B finira toujours par valoir 0.
                                                              Le pire des cas étant le calcul (-1) + (1) (qui permet de montrer que le pire des cas de l'algo est O(n) n étant le nombre de bits pour stocker l'entier.)

                                                              pire des cas sur 8 bits.

                                                              -1 + 1
                                                              -2 + 2
                                                              -4 + 4
                                                              -8 + 8
                                                              -16 + 16
                                                              -32 + 32
                                                              -64 + 64
                                                              -128 + -128
                                                              0 + 0
                                                              = 0

                                                              On peut sentir que ce n'est pas très optimal dans ce cas !


                                                              -
                                                              Edité par neuneutrinos 24 février 2020 à 15:53:10

                                                              • Partager sur Facebook
                                                              • Partager sur Twitter

                                                              Addition sans le signe "+"

                                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                              • Editeur
                                                              • Markdown