Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 12/08/2010, à 11:58

HP

[FIXED] int size = ((int) ceil ((r * 3)) + 1) & ~1;

Bon, j'ai un petit souci… vraiment minime
j'ai, le code n'est évidemment pas de moi, cette ligne :

int size = ((int) ceil ((r * 3)) + 1) & ~1;

bon, déjà je ne comprends pas tout : je ne sais pas à quoi servent l'esperluette suivi du tilde et de 1 ?!
ensuite à la compilation ça me sort un warning :

  CC     xcompmgr.o
In file included from xcompmgr.c:71:
inc/functions.h: In function ‘make_gaussian_map’:
inc/functions.h:179: warning: cast from function call of type ‘double’ to non-matching type ‘int’

J'aimerais bien réussir… et à supprimer sur ce warning et, en y étant, à légèrement améliorer la syntaxe de cette ligne. Alors, si quelqu'un a une idée.

Dernière modification par HP (Le 12/08/2010, à 13:33)


cat /dev/urandom >/dev/null 2>&1 #github

Hors ligne

#2 Le 12/08/2010, à 12:26

McGee

Re : [FIXED] int size = ((int) ceil ((r * 3)) + 1) & ~1;

Bonjour,

Dans le détail:

- La fonction ceil() arrondit x par excès à l'entier le plus proche.

- Le cast en int permet de récupérer uniquement la partie entière du résultat de ceil (qui retourne un double).

- L'opérateur '&' effectue un ET bit-à-bit, c'est de l'algèbre de boole.
Par exemple: 9 (1001) & 12 (1100) = 8 (1000)

- l'opérateur ~ est le complement a 1
Par exemple: ~11110000=00001111

- Les () sont juste là pour définir une priorité des opérations. (tout comme en mathématique)

Dernière modification par McGee (Le 12/08/2010, à 12:31)


"Ce n'est pas parce qu'ils sont plusieurs à avoir tort qu'ils ont forcément raison."
(Coluche)

-- Mes excuses pour les accents, je suis sur un QWERTY

Hors ligne

#3 Le 12/08/2010, à 12:30

HP

Re : [FIXED] int size = ((int) ceil ((r * 3)) + 1) & ~1;

McGee a écrit :

Le cast en int est pour éviter un warning (ceil retourne un double).

Ce qui ne fonctionne visiblement pas, ou alors une subtilité m'échappe… cf la sortie de make hmm.


cat /dev/urandom >/dev/null 2>&1 #github

Hors ligne

#4 Le 12/08/2010, à 12:32

McGee

Re : [FIXED] int size = ((int) ceil ((r * 3)) + 1) & ~1;

Bonjour,
Désolé j'éditais mon poste au fur et à mesure.
Il est difficile de trouver un soucis avec une seule ligne.
Donne nous la ligne 179 du fichier functions.h

EDIT://
Donne nous aussi le type de r

Dernière modification par McGee (Le 12/08/2010, à 12:34)


"Ce n'est pas parce qu'ils sont plusieurs à avoir tort qu'ils ont forcément raison."
(Coluche)

-- Mes excuses pour les accents, je suis sur un QWERTY

Hors ligne

#5 Le 12/08/2010, à 12:34

HP

Re : [FIXED] int size = ((int) ceil ((r * 3)) + 1) & ~1;

McGee a écrit :

Donne nous la ligne 179 du fichier functions.h

C'est celle ci… faudrait juste l'améliorer.
Et r est un double :

static conv * make_gaussian_map (Display *dpy, double r)

Dernière modification par HP (Le 12/08/2010, à 12:34)


cat /dev/urandom >/dev/null 2>&1 #github

Hors ligne

#6 Le 12/08/2010, à 12:49

McGee

Re : [FIXED] int size = ((int) ceil ((r * 3)) + 1) & ~1;

Le problème ne vient pas de cette ligne précise.
Certes, elle doit être améliorable (je vois déjà une paire de parenthèse qui ne sers a rien)

#include <stdio.h>
#include <math.h>

int             main(void)
{
  double        r       = 3.1416;
  int           size    = ((int) ceil(r * 3) + 1) & ~1;

  printf("size = '%d'\n", size);
  return (0);
}
mcgee@clonix-laptop:/tmp/src$ gcc -W -Wall -ansi -pedantic main.c -lm -o test
mcgee@clonix-laptop:/tmp/src$

EDIT://
Âpres quelques tests, il semblerait que l'instruction x & ~1 permette d'arrondir au multiple de deux inférieurs, ce qui reviendrait a faire -1 si le résultat est impair. (cela évite donc d'effectuer une condition, c'est plutôt optimise)

#include <stdio.h>

int             main(void)
{
  printf("0 & ~1 = '%d'\n", 0 & ~1);
  printf("1 & ~1 = '%d'\n", 1 & ~1);
  printf("2 & ~1 = '%d'\n", 2 & ~1);
  printf("3 & ~1 = '%d'\n", 3 & ~1);
  printf("4 & ~1 = '%d'\n", 4 & ~1);
  printf("5 & ~1 = '%d'\n", 5 & ~1);
  printf("6 & ~1 = '%d'\n", 6 & ~1);
  printf("7 & ~1 = '%d'\n", 7 & ~1);
  printf("8 & ~1 = '%d'\n", 8 & ~1);
  printf("9 & ~1 = '%d'\n", 9 & ~1);
  printf("10 & ~1 = '%d'\n", 10 & ~1);
  printf("42 & ~1 = '%d'\n", 42 & ~1);
  printf("1337 & ~1 = '%d'\n", 1337 & ~1);
  return (0);
}
mcgee@clonix-laptop:/tmp/src$ gcc -W -Wall -ansi -pedantic main.c -o test
mcgee@clonix-laptop:/tmp/src$ ./test 
0 & ~1 = '0'
1 & ~1 = '0'
2 & ~1 = '2'
3 & ~1 = '2'
4 & ~1 = '4'
5 & ~1 = '4'
6 & ~1 = '6'
7 & ~1 = '6'
8 & ~1 = '8'
9 & ~1 = '8'
10 & ~1 = '10'
42 & ~1 = '42'
1337 & ~1 = '1336'
mcgee@clonix-laptop:/tmp/src$

Dernière modification par McGee (Le 12/08/2010, à 13:12)


"Ce n'est pas parce qu'ils sont plusieurs à avoir tort qu'ils ont forcément raison."
(Coluche)

-- Mes excuses pour les accents, je suis sur un QWERTY

Hors ligne

#7 Le 12/08/2010, à 13:02

HP

Re : [FIXED] int size = ((int) ceil ((r * 3)) + 1) & ~1;

McGee a écrit :

Le problème ne vient pas de cette ligne précise.
Certes, elle doit être améliorable (je vois déjà une paire de parenthèse qui ne sers a rien)

#include <stdio.h>
#include <math.h>

int             main(void)
{
  double        r       = 3.1416;
  int           size    = ((int) ceil(r * 3) + 1) & ~1;

  printf("size = '%d'\n", size);
  return (0);
}

Bon alors essaie :

CWARNFLAGS='-Wall -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -fno-strict-aliasing -Wbad-function-cast -Wold-style-definition -Wdeclaration-after-statement '
gcc $CWARNFLAGS -lm 'test.c'

Et là… tada :

test.c: In function ‘main’:
test.c:7: warning: cast from function call of type ‘double’ to non-matching type ‘int’

Le warning semble bien être la même…

Dernière modification par HP (Le 12/08/2010, à 13:10)


cat /dev/urandom >/dev/null 2>&1 #github

Hors ligne

#8 Le 12/08/2010, à 13:28

McGee

Re : [FIXED] int size = ((int) ceil ((r * 3)) + 1) & ~1;

le warning est provoquer par -Wbad-function-cast, hors si j'en crois la doc

-Wbad-function-cast (C and Objective-C only)
      Warn whenever a function call is cast to a non-matching type.  For
      example, warn if "int malloc()" is cast to "anything *".

Je pense que ca warning parcequ'il y a perte d'information.


"Ce n'est pas parce qu'ils sont plusieurs à avoir tort qu'ils ont forcément raison."
(Coluche)

-- Mes excuses pour les accents, je suis sur un QWERTY

Hors ligne

#9 Le 12/08/2010, à 13:30

HP

Re : [FIXED] int size = ((int) ceil ((r * 3)) + 1) & ~1;

C'était bien un souci de parenthèse…

Version sans warning :

#include <stdio.h>
#include <math.h>

int conv(double r);
int conv(double r) { return (int)(ceil(r * 3) + 1) & ~1; }

int main(void) {
    printf("conv(0)    = '%d'\n", conv(0));
    printf("conv(1)    = '%d'\n", conv(1));
    printf("conv(2)    = '%d'\n", conv(2));
    printf("conv(3)    = '%d'\n", conv(3));
    printf("conv(4)    = '%d'\n", conv(4));
    printf("conv(5)    = '%d'\n", conv(5));
    printf("conv(6)    = '%d'\n", conv(6));
    printf("conv(7)    = '%d'\n", conv(7));
    printf("conv(8)    = '%d'\n", conv(8));
    printf("conv(9)    = '%d'\n", conv(9));
    printf("conv(10)   = '%d'\n", conv(10));
    printf("conv(12)   = '%d'\n", conv(42));
    printf("conv(1337) = '%d'\n", conv(1337));
    return (0);
}

Résultat attendu :

gcc $CWARNFLAGS -lm 'test.c' -o testm && ./testm
conv(0)    = '0'
conv(1)    = '4'
conv(2)    = '6'
conv(3)    = '10'
conv(4)    = '12'
conv(5)    = '16'
conv(6)    = '18'
conv(7)    = '22'
conv(8)    = '24'
conv(9)    = '28'
conv(10)   = '30'
conv(12)   = '126'
conv(1337) = '4012'

Par contre, je doute que l'on puisse vraiment en améliorer la syntaxe…

Dernière modification par HP (Le 12/08/2010, à 13:35)


cat /dev/urandom >/dev/null 2>&1 #github

Hors ligne

#10 Le 12/08/2010, à 13:41

McGee

Re : [FIXED] int size = ((int) ceil ((r * 3)) + 1) & ~1;

Donc plus de probleme de warning, c'est deja ca de pris roll
La syntaxe n'est pas intuitive, mais optimisée.
Je te conseille de séparer la déclaration et l'initialisation de ta variable.
Si tu trouves vraiment pas ca lisible, tu peux simplement rajouter une condition.


"Ce n'est pas parce qu'ils sont plusieurs à avoir tort qu'ils ont forcément raison."
(Coluche)

-- Mes excuses pour les accents, je suis sur un QWERTY

Hors ligne

#11 Le 12/08/2010, à 13:52

HP

Re : [FIXED] int size = ((int) ceil ((r * 3)) + 1) & ~1;

Le même genre de code mettant en évidence la fonction levant un warning, wconv(), et la version corrigée :

#include <stdio.h>
#include <math.h>

int gconv(double r);
int wconv(double r);

int gconv(double r) { return (int)(ceil(r * 3) + 1) & ~1; }
int wconv(double r) { return ((int) ceil(r * 3) + 1) & ~1; }

int main(void) {
    printf("conv(0)          = '%d'    '%d'\n", gconv(0), wconv(0));
    printf("conv(1)          = '%d'    '%d'\n", gconv(1), wconv(1));
    printf("conv(2)          = '%d'    '%d'\n", gconv(2), wconv(2));
    printf("conv(3)          = '%d'   '%d'\n", gconv(3), wconv(3));
    printf("conv(4)          = '%d'   '%d'\n", gconv(4), wconv(4));
    printf("conv(5)          = '%d'   '%d'\n", gconv(5), wconv(5));
    printf("conv(6)          = '%d'   '%d'\n", gconv(6), wconv(6));
    printf("conv(7)          = '%d'   '%d'\n", gconv(7), wconv(7));
    printf("conv(8)          = '%d'   '%d'\n", gconv(8), wconv(8));
    printf("conv(9)          = '%d'   '%d'\n", gconv(9), wconv(9));
    printf("conv(10)         = '%d'   '%d'\n", gconv(10), wconv(10));
    printf("conv(12)         = '%d'  '%d'\n", gconv(42), wconv(42));
    printf("conv(1337)       = '%d' '%d'\n", gconv(1337), wconv(1337));
    printf("conv(1337.24456) = '%d' '%d'\n", gconv(1337.24456), wconv(1337.24456));
    printf("conv(π)          = '%d'   '%d'\n", gconv(3.141593), wconv(3.141593));
    printf("conv(339/108)    = '%d'   '%d'\n", gconv(339/108), wconv(339/108));
    return (0);
}
gcc $CWARNFLAGS -lm 'test.c' -o testm && ./testm 
test.c: In function ‘wconv’:
test.c:8: warning: cast from function call of type ‘double’ to non-matching type ‘int’
conv(0)          = '0'    '0'
conv(1)          = '4'    '4'
conv(2)          = '6'    '6'
conv(3)          = '10'   '10'
conv(4)          = '12'   '12'
conv(5)          = '16'   '16'
conv(6)          = '18'   '18'
conv(7)          = '22'   '22'
conv(8)          = '24'   '24'
conv(9)          = '28'   '28'
conv(10)         = '30'   '30'
conv(12)         = '126'  '126'
conv(1337)       = '4012' '4012'
conv(1337.24456) = '4012' '4012'
conv(π)          = '10'   '10'
conv(339/108)    = '10'   '10'

Voilà… je ne sais pas si ça suffit comme jeu de test, mais les résultats semblent identiques.


cat /dev/urandom >/dev/null 2>&1 #github

Hors ligne

#12 Le 12/08/2010, à 14:05

McGee

Re : [FIXED] int size = ((int) ceil ((r * 3)) + 1) & ~1;

Il y a toutes les chances que les résultats soit identiques.


"Ce n'est pas parce qu'ils sont plusieurs à avoir tort qu'ils ont forcément raison."
(Coluche)

-- Mes excuses pour les accents, je suis sur un QWERTY

Hors ligne

#13 Le 12/08/2010, à 14:30

yannzbig

Re : [FIXED] int size = ((int) ceil ((r * 3)) + 1) & ~1;

Normal que les résultats soient identiques, la fonction corrigée fait un cast en "int" de (ceil() +1.), au lieu de caster d'abord ceil(), puis ajouter 1, ce qui revient au même du point de vue du calcul.

Du point de vue de l'optimisation, je dirais intuitivement que calculer

(int)ceil() + 1 (--> addition d'entiers)

est plus rapide que

(int) (ceil() + 1.)  (--> addition de doubles)

A confirmer. Si c'est le cas tu ne devrais pas t'affranchir du warning..

Pour pouvoir améliorer ta fonction, il serait bien d'avoir quelques conditions supplémentaires sur r (genre r positif ou nul ...)