Partage
  • Partager sur Facebook
  • Partager sur Twitter

Codage d'une décomposition

4 octobre 2012 à 22:14:56

je suis passé a une utilisation intensive d'un langage de plus haut niveau avant de tâter du flag x) je me débrouille globalement bien en C mais je n'ai jamais encore tenté des choses tendues. comme y inserer de l'asm ou toucher au multi threading ^^ (par contre en java j'en ai partout, mais ils sont justifiés x) )
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
4 octobre 2012 à 22:15:09

perso je les utilise presque tout le temps, mais là à vue de nez va falloir bidouiller pour trouver un truc qui fonctionne. Le problème vient du fait qu'on raisonne en base 10...
  • Partager sur Facebook
  • Partager sur Twitter
4 octobre 2012 à 22:39:56

Sinon quand tu sais que diviser par 10 revient à multiplier par 0.1, y'a plus besoin de se faire chier. Le principe serait le suivant :

Tu multiplies ton nombre par 0.1. Ce que tu vas obtenir est l'unité, après la virgule.
Ensuite, tu retiens le nombre entier dans une variable intermédiaire, tu retranches ce nombre au résultat initial, et tu multiplies par 10, ce qui va te donner l'unité. Ensuite tu prends ce même résultat, tu le met en "paramètre", et tu réitères l'opération.

Je sais pas si je suis clair mais en gros voici un exemple :

Soit x un nombre à k digits à la base
double res = x * 0.1
double digit = (res - (int)res) * 10
x = res
maintenant x est un nombre à k-1 digits
réitérer l'opération

après à toi de te débrouiller pour isoler l'unité, le dixième, etc..


  • Partager sur Facebook
  • Partager sur Twitter
4 octobre 2012 à 23:40:36

Aller, je me suis éclaté. J'ai pas fait de fonctions, un vieux c/c. Pas taper !
Enjoy !

#include <stdio.h>
#include <stdlib.h>

int main(void) {
  unsigned long long a;
  unsigned int * b;
  unsigned int * e;
  int u, d, c, m;
  int n;
  
  scanf("%d", &n);
  
  
  /* Unités */
  a = 0x66666667;
  a *= n;
  
  b = (unsigned int *) &a;
  e = b + 1;
  
  *e = (*e) >> 0x2;
  
  u = n - (*e * 0xA);
  n = *e;
  
  /* Dizaines */
  a = 0x66666667;
  a *= n;
  
  b = (unsigned int *) &a;
  e = b + 1;
  
  *e = (*e) >> 0x2;
  
  d = n - (*e * 0xA);
  n = *e;
  
  /* Centaines */
  a = 0x66666667;
  a *= n;
  
  b = (unsigned int *) &a;
  e = b + 1;
  
  *e = (*e) >> 0x2;
  
  c = n - (*e * 0xA);
  n = *e;  
  
  /* Milliers */
  a = 0x66666667;
  a *= n;
  
  b = (unsigned int *) &a;
  e = b + 1;
  
  *e = (*e) >> 0x2;
  
  m = n - (*e * 0xA);
  n = *e;
  
  
  printf("m : %d\n", m);
  printf("c : %d\n", c);
  printf("d : %d\n", d);
  printf("u : %d\n", u);
  
  return EXIT_SUCCESS;
}

  • Partager sur Facebook
  • Partager sur Twitter
5 octobre 2012 à 11:28:24

A mon tour de faire du copier coller.

#include <stdio.h>

int main(void)
{
   int n;
   int m = 0, c = 0, d = 0, u = 0;

   scanf("%d", &n);

   (++m, !((n-m*1000)>>(8*sizeof(n)-1))) &&
   (++m, !((n-m*1000)>>(8*sizeof(n)-1))) &&
   (++m, !((n-m*1000)>>(8*sizeof(n)-1))) &&
   (++m, !((n-m*1000)>>(8*sizeof(n)-1))) &&
   (++m, !((n-m*1000)>>(8*sizeof(n)-1))) &&
   (++m, !((n-m*1000)>>(8*sizeof(n)-1))) &&
   (++m, !((n-m*1000)>>(8*sizeof(n)-1))) &&
   (++m, !((n-m*1000)>>(8*sizeof(n)-1))) &&
   (++m, !((n-m*1000)>>(8*sizeof(n)-1)));
   --m;
   n -= m*1000;
   (++c, !((n-c*100)>>(8*sizeof(n)-1))) &&
   (++c, !((n-c*100)>>(8*sizeof(n)-1))) &&
   (++c, !((n-c*100)>>(8*sizeof(n)-1))) &&
   (++c, !((n-c*100)>>(8*sizeof(n)-1))) &&
   (++c, !((n-c*100)>>(8*sizeof(n)-1))) &&
   (++c, !((n-c*100)>>(8*sizeof(n)-1))) &&
   (++c, !((n-c*100)>>(8*sizeof(n)-1))) &&
   (++c, !((n-c*100)>>(8*sizeof(n)-1))) &&
   (++c, !((n-c*100)>>(8*sizeof(n)-1)));
   --c;
   n -= c*100;
   (++d, !((n-d*10)>>(8*sizeof(n)-1))) &&
   (++d, !((n-d*10)>>(8*sizeof(n)-1))) &&
   (++d, !((n-d*10)>>(8*sizeof(n)-1))) &&
   (++d, !((n-d*10)>>(8*sizeof(n)-1))) &&
   (++d, !((n-d*10)>>(8*sizeof(n)-1))) &&
   (++d, !((n-d*10)>>(8*sizeof(n)-1))) &&
   (++d, !((n-d*10)>>(8*sizeof(n)-1))) &&
   (++d, !((n-d*10)>>(8*sizeof(n)-1))) &&
   (++d, !((n-d*10)>>(8*sizeof(n)-1)));
   --d;
   n -= d*10;
   (++u, !((n-u)>>(8*sizeof(n)-1))) &&
   (++u, !((n-u)>>(8*sizeof(n)-1))) &&
   (++u, !((n-u)>>(8*sizeof(n)-1))) &&
   (++u, !((n-u)>>(8*sizeof(n)-1))) &&
   (++u, !((n-u)>>(8*sizeof(n)-1))) &&
   (++u, !((n-u)>>(8*sizeof(n)-1))) &&
   (++u, !((n-u)>>(8*sizeof(n)-1))) &&
   (++u, !((n-u)>>(8*sizeof(n)-1))) &&
   (++u, !((n-u)>>(8*sizeof(n)-1)));
   --u;

   printf("milliers : %d\n"
          "centaine : %d\n"
          "dizaine  : %d\n"
          "unite    : %d\n",
          m, c, d, u);
   return 0;
   
}



Techniquement je ne fais pas de test, le code ne fait que d'évaluer des expressions ayant des effets de bords intéressants. :-°

Vive l'édition en mode colonne.
  • Partager sur Facebook
  • Partager sur Twitter
Zeste de Savoirbépocode minimal  — Ge0 <3
5 octobre 2012 à 15:01:19

A ce moment-là c'est pas vraiment un code qu'on attend d'un débutant ^^ la méthode que j'ai proposée est plus simple (bon d'accord, ça fait intervenir des double, et ce serait chiant sur un processeur sans unité flottante, mais je pense pas que ça soit leur préoccupation première pour le moment x) )
  • Partager sur Facebook
  • Partager sur Twitter
5 octobre 2012 à 15:53:39

@simbilou : je ne serai pas contre un peu de commentaire dans le code :p
  • Partager sur Facebook
  • Partager sur Twitter
5 octobre 2012 à 16:46:57

L'idée est de compter le nombre de fois qu'il faut retrancher 1000 au nombre avant qu'il ne soit négatif. Ensuite on retranche les milliers du nombre (on vient de les calculer) et on recommence avec les centaines, etc..

Le code devient un peu plus clair quand on sait que !((n-m*1000)>>(8*sizeof(n)-1)) est juste une manière tordu d'écrire n-m*1000 >= 0 (on regarde le bit de signe en fait). Ensuite je me sert de l'évaluation en court-circuit qui fait que l'expression a droite de l'opérateur && ne sera pas évaluée si l'expression de gauche est fausse. Pour finir, l'opérateur virgule (,) me permet d'incrémenter tranquillement mon compteur sans intervenir dans la valeur de l'expression en elle-même.

Sinon moi c'est le code de pouet qui m'intrigue. :o
  • Partager sur Facebook
  • Partager sur Twitter
Zeste de Savoirbépocode minimal  — Ge0 <3
Anonyme
5 octobre 2012 à 16:55:16

Citation

L'idée est de compter le nombre de fois qu'il faut retrancher 1000 au nombre avant qu'il ne soit négatif.



c'est le principe de la division. :D
  • Partager sur Facebook
  • Partager sur Twitter
5 octobre 2012 à 17:32:43

Citation : simbilou

Sinon moi c'est le code de pouet qui m'intrigue. :o


C'est marrant que tu sois le seul à me demander ça. Les autres ont compris ? :lol:
  • Partager sur Facebook
  • Partager sur Twitter
5 octobre 2012 à 21:17:46

ha je comprends mieux :)

en effet, le code de pouet m'intrique aussi, même si j'ai cru pendant un moment avoir presque compris :p

du coup je ne suis pas contre une explication non plus x)
  • Partager sur Facebook
  • Partager sur Twitter
5 octobre 2012 à 22:10:58

L'explication mathématique je la connais pas, mais je vous explique le principe. :)
Le but c'est de prendre l'entier sur 32 bits et de faire une multiplication pour avoir un débordement sur 64 bits. On a la partie 'gauche' (32bits) et la partie 'droite' (32 autres bits). Le but c'est de prendre les 32 bits et de faire un décalage de 2 pour avoir le résultat. :)
J'ai fait une division par 10. Pour avoir le modulo 10, il suffit de prendre le résultat de la division, de le multiplier par 10 et de soustraire ce résultat au nombre de départ.

int main(void) {
  unsigned long long a;
  unsigned int * b;
  unsigned int * e;
  int u;
  int n = 4567;

  /* Unités */
  a = 0x66666667;
  a *= n; /* Multiplication pour débordement 64 bits */
  
  b = (unsigned int *) &a; /* On récupère la 1ère partie 32 bits */
  e = b + 1; /* La seconde partie 32 bits */
  
  *e = (*e) >> 0x2; /* Le décalage */

  /* A ce stade, *e vaut 456 */  

  u = n - (*e * 0xA); /* Le modulo : 4567 - (456*10) = 4567 - 4560 = 7  */
  n = *e; /* On stocke le résultat pour récupérer les nombres restants */

Le code en lui-même est complet pour ce que je cherche à faire, mais incomplet pour finir la division. ^^
Ya d'autres trucs à prendre en compte, mais j'ai zappé puisque ça ne me concerne pas.
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
5 octobre 2012 à 22:16:12

Pouet_forever, je dois avouer que je suis impressionné, y a vraiment des gens balaises sur ce forum. ^^
En tout cas j'aurais peut-être pas trouvé, et l'idée est pas mal du tout, vraiment original, et pour le coup si le PO montre ça à son prof, il va faire une tête du genre : :waw:

Sinon là je crois que le PO a largement de quoi faire, à mon avis on a épuisé pas mal de possibilités, et si la consigne est bien celle-là, alors les codes qu'on a donné suffisent à mon avis.
  • Partager sur Facebook
  • Partager sur Twitter
5 octobre 2012 à 22:47:28

Bah, j'ai pas trouvé tout seul non plus, j'ai un peu cherché. ^^
J'ai joué avec l'assembleur et j'ai vu ce que je pouvais faire en C après. :)
  • Partager sur Facebook
  • Partager sur Twitter
5 octobre 2012 à 23:22:57

Tu peux toujours t'amuser à faire la preuve de ton programme =D

(En plus y'a pas de boucle, c'est le bonheur x) )
  • Partager sur Facebook
  • Partager sur Twitter
6 octobre 2012 à 0:16:00

Le code de Pouet_forever retranscrit en décimal.

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  /* a = 0x66666667;
     b = 0x400000000; // 2³⁴
  */
  unsigned long long a = 1717986919, b = 17179869184;

  int u, d, c, m;
  int n,e;
  
  scanf("%d", &n);
  
  /* Unités */
  e = (n * a) / b;
  u = n - (e * 10);
  n = e;
  
  /* Dizaines */
  e = (n * a) / b;
  d = n - (e * 10);
  n = e;
  
  /* Centaines */
  e = (n * a) / b;
  c = n - (e * 10);
  n = e;
  
  /* Milliers */
  e = (n * a) / b;
  m = n - (e * 10);
  n = e;
  
  printf("m : %d\n", m);
  printf("c : %d\n", c);
  printf("d : %d\n", d);
  printf("u : %d\n", u);
  
  return EXIT_SUCCESS;
}


Donc cette « technique » ne marchera pas indéfiniment (b != 10*a).
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
6 octobre 2012 à 0:17:41

@sildre : la division est interdite !
  • Partager sur Facebook
  • Partager sur Twitter
6 octobre 2012 à 0:21:15

Citation : Bin-R

@sildre : la division est interdite !

Je sais, ce que j'ai proposé n'étais pas pour répondre au sujet, c'était pour améliorer la compréhension du code de Pouet.
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
6 octobre 2012 à 0:25:02

ah ok, j'avais pas compris. :)
  • Partager sur Facebook
  • Partager sur Twitter
4 décembre 2019 à 8:37:50

Bien qu'ancien voici une solution : 
int a=1234;
char s[4];
sprintf(s,"%d",a);
printf("%c",s[0]
  • Partager sur Facebook
  • Partager sur Twitter
4 décembre 2019 à 9:11:22

Bonjour,

Déterrage

Citation des règles générales du forum :

Avant de poster un message, vérifiez la date du sujet dans lequel vous comptiez intervenir.

Si le dernier message sur le sujet date de plus de deux mois, mieux vaut ne pas répondre.
En effet, le déterrage d'un sujet nuit au bon fonctionnement du forum, et l'informatique pouvant grandement changer en quelques mois il n'est donc que rarement pertinent de déterrer un vieux sujet.

Au lieu de déterrer un sujet il est préférable :

  • soit de contacter directement le membre voulu par messagerie privée en cliquant sur son pseudonyme pour accéder à sa page profil, puis sur le lien "Ecrire un message"
  • soit de créer un nouveau sujet décrivant votre propre contexte
  • ne pas répondre à un déterrage et le signaler à la modération

Je ferme ce sujet. En cas de désaccord, me contacter par MP.

  • Partager sur Facebook
  • Partager sur Twitter
Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL