Dans les kiosques cet été 2011

Posté par (page perso) . Modéré par Lucas Bonnet. Licence CC by-sa
26
7
août
2011
Presse

Petite sélection de ce que l'on peut retrouver cet été dans la presse.

Sommaire

Sous le titre « Menaces sur le Web : Tim Berners‐Lee, son créateur, s’inquiète », Pour la Science № 404 ouvre ses colonnes au Britannique sur 6 pages. À noter aussi la rubrique Logique et calcul de Jean‐Paul Delahaye qui ce mois‐ci s’intéresse aux calculateurs sans mémoire. La section geek friendly parle de micro satellites standards faits maison (cubesats).

Linux Pratique n° 65 (mai-juin)

Linux Pratique n°65 fait son gros titre sur le SDK Android et consacre un grand nombre de ses pages à ce sujet, mais n'oublie pas de se focaliser sur l'utilisation productive des logiciels libres (Darktable, la poule ou l'œuf…).

Linux Mag HS n° 55, juillet-août, spécial C/C++

Linux Mag HS n°55 est un numéro spécial C/C++. À l'ère des langages (interprétés ou compilés) réputés plus abordables (Python, Ruby, Java), des langages orientés "développement Web" (PHP) pour lesquelles on trouve un tas de bibliothèques et de frameworks permettant de faire à peu près tout ce que l'on veut, quel est l'intéret du C ou du C++ aujourd'hui ? C'est la question que l'on peut se poser, et ce hors-série apporte quelques réponses à cette question. Après un article d'introduction au C (historique et technique), puis une présentation de la norme C++0x (nouvelle version de la norme C++), vous aurez droit à une série d'articles permettant d'écrire des extensions C/C++ pour les environnements/langages les plus utilisés du moment :

Ce numéro nous montre que, même s'ils sont de moins en moins utilisés pour le développement d'applications de haut niveau, ce serait une erreur de dénigrer ces vénérables langages que sont le C et son descendant direct, le C++. En effet, ils peuvent s'avérer incontournables lorsqu'on a besoin de performance, de code compact, ou lorsque les outils/langages de plus haut niveau que nous utilisons habituellement montrent leurs limites et nécessitent d'être étendus.

  • compilation de sources C/C++ pour Androïd ;
  • écrire des extensions pour PHP ;
  • écrire des extensions pour Python ;
  • intégrer un moteur de script LUA dans son code C/C++.

En prime vous aurez droit à un petit tutoriel du débugger GDB, et une initiation à la preuve de programme avec Frama-C (je ne l'ai pas lu, je ne vous ferai donc pas de commentaire sur cet article).

MISC n° 56 juillet-août

Dans ce numéro de MISC n°56, nous avons droit à l'habituel exploit corner. Ici, il s'agit d'exploiter la vulnérabilité d'un Active X dans un environnement Windows 7 a jour, avec les protections DEP et ASLR activée. On continuera avec le malware corner où l'on étudiera l'un des logiciels malveillants les plus actifs ces dernières années dans le domaine du vol de compte de jeux vidéos en ligne. On enchainera avec le pentest corner où l'on apprendra le fonctionnement de DPAPI, le moteur de chiffrement de Windows. On arrivera alors au dossier du mois : "Forensics, les nouveaux enjeux". Le premier article nous parle de la recherche de preuve sur un système "vivant" dans le cadre d'une enquête judiciaire. Le second article nous montre une analyse du framework volatility, permettant l'analyse de l'image mémoire d'un système Windows. Le troisième article est une interview du célèbre blogueur Zythom.
Ensuite, nous découvrons le protocole EMV-CAP, utilisé par les "calculettes" founies par de plus en plus de banques pour s'authentifier avant d'accèder à leurs services. On enchaine avec une présentation de W3AF, un scanner web open source qui souhaite devenir la référence dans son domaine, et est en bonne voie pour ! On termine ce numéro estival avec un article nous présentant brièvement l'architecture de GCC pour développer de petits plugins afin de créer ses propres outils d'analyse de code.

Linux Mag n° 140, juillet-août

Dans ce numéro Linux Mag n°140, nous avons droit aux habituels actualités du noyau (ici, le 2.6.39). On découvre ensuite une utilisation de trac en tant que système de ticket, mais piloté uniquement par mail, puis on aborde brièvement la virtualisation, avec l'utilisation de virt-manager et virsh afin de mettre en place une salle de TP. On nous expose ensuite différents outils pour mesurer les performances des systèmes de stockages, et on enchaine avec de l'embarqué : d'abord un peu de VHDL, puis un article dédié à l'utilisation de la plateforme arduino. Attention, connaissance préalable d'arduino plus que recommandée avant d'aborder cet article. On approfondit ensuite notre connaissance du reverse-proxy cache HTTP Varnish, déjà abordé dans GLMF 138, avant d'aborder les différentes possibilités d'interconnexion entre réseau IPv4 et IPv6. On continue avec un retour d'expérience de la mise à jour manuelle en Android 2.3.4 d'un Galaxy S, sans utilisation de Mirosoft Windows. Enfin, ce magazine se termine en utilisant CUDA pour réaliser la simulation du drapé d'une nappe sur une table, en simulant un tissu simple.

OpenSilicium n° 3

C'est « l'heure de la confirmation » pour cet OpenSilicium n° 3, en synthèse de l'édito de Denis Bodor. Cette fois-ci, la robotique mais pas seulement : contrôleur de servomoteurs FPGA sur plate-forme Armadeus, mobilité avec android, expérimenter avec arduino et autres sujets. Vivement la suite avec encore des articles variés, suivis et de nombreux sujets.

Notes subjectives de lecture de Pour la Science

Chronique de Tim Berners Lee

Voici un an que le brevet sur le web déposé en 1990 par Tim Berners Lee est arrivé à expiration. Coup de génie de sa part, qui le place bien au delà des « coups » de Mark Shuttleworth, ou même Steve Jobs et Bill Gates, puisqu'en vingt ans il a pu licencier son invention à un pourcentage impressionnant des Terriens, sans compter le renouvellement des normes pour permettre à chaque plateforme d'accéder à chaque site et à chacun de publier un site différent de celui du voisin.

Cette illustration maladroite de ce que pourrait être le monde si Tim Berners Lee n'était qu'un technicien cynique et non un visionnaire (pas de révolutions via le web…) est là pour vous donner envie de lire sa très bonne tribune, dans laquelle il rappelle que les fondamentaux droits fondamentaux humains passent désormais par le droit de lire et publier sur l'Internet, via le web, par des URI, la neutralité du contenu vis-à vis des plateformes et la neutralité du réseau vis-à-vis des contenus. En plus il y a de superbes illustrations trollesques de John Hendrix (NdM : site inaccessible au moment de la relecture de la dépêche) que j'encadrerais volontiers.

Tous les concepts sont abordés, c'est dense mais clair : lisez et ensuite, faites lire !

Article de Jean-Paul Delahaye

Comme chaque mois, Jean-Paul Delahaye nous prend par la main vers des mondes mathématiques souvent bien hors de ma portée. Ce mois-ci, le défi est découvrir le calcul in situ et construire une algorithmique qui réutilise l'espace mémoire des données en entrée pour calculer le résultat, et rien de plus.

Exemple : la permutation de A et B, là où habituellement nous utilisons une variable tampon :

A := A + B;
B := A - B;
A := A - B;

Des exemples sont bien sûr donnés pour le calcul matriciel.

L'intérêt général est d'éviter de perdre des cycles CPU en réalisant de coûteux accès à la mémoire. Cet algorithmique semble magique (qu'arrive-t-il à l'exemple ci-dessus si "A + B" provoque un dépassement de capacité ?) et simple (une fois qu'on a les résultats devant les yeux), mais en est encore à ses débuts et pose d'intéressants problèmes non triviaux à résoudre.

  • # Autre méthode

    Posté par . Évalué à 10.

    Exemple : la permutation de A et B, là ou habituellement nous utilisons une variable tampon :

    A := A + B;
    B := A - B;
    A := A - B;

    Je le connaissait avec des opérations binaires :

    int a = 42;
    int b = 13;
    
    a ^= b;
    b ^= a;
    a ^= b;
    

    Les logiciels sous licence GPL forcent leurs utilisateurs à respecter la GPL (et oui, l'eau, ça mouille).

    • [^] # Re: Autre méthode

      Posté par (page perso) . Évalué à 4.

      Joli. En plus cela supprime les problèmes éventuels de débordement.

      • [^] # Re: Autre méthode

        Posté par (page perso) . Évalué à 9. Dernière modification le 07/08/11 à 17:34.

        Je n'ai pas lu l'article, mais ça avait l'air marrant alors j'ai testé rapidement en C++ :

        #include <iostream>
        #include <limits>
        #include <typeinfo>
        
        using namespace std;
        
        template <typename T> void swap1(T & A, T & B) {
          T oldA = A;
          T oldB = B;
          A = A + B;
          B = A - B;
          A = A - B;
          if (!((A==oldB) && (B==oldA))) {
            cout << "swap+\ttype=" << typeid(T).name()
             << "\tavant A=" << oldA << "\tB=" << oldB
             << "\taprès A=" << A << "\tB=" << B << endl;
          }
        }
        
        template <typename T> void swap2(T & A, T & B) {
          T oldA = A;
          T oldB = B;
          A ^= B;
          B ^= A;
          A ^= B;
          if (!((A==oldB) && (B==oldA))) {
            cout << "swap^\ttype=" << typeid(T).name()
             << "\tavant A=" << oldA << "\tB=" << oldB
             << "\taprès A=" << A << "\tB=" << B << endl;
          }
        }
        
        template <typename T> void letsTest(void (*swap)(T&, T&)) {
          T a;
          T b;
        
          a = 42; b = 69; (*swap)(a,b);
          a = numeric_limits<T>::max(); b = 42; (*swap)(a,b);
          a = numeric_limits<T>::min(); b = 42; (*swap)(a,b);
          a = numeric_limits<T>::max(); b = numeric_limits<T>::max(); (*swap)(a,b);
          a = numeric_limits<T>::min(); b = numeric_limits<T>::max(); (*swap)(a,b);
          a = numeric_limits<T>::max(); b = numeric_limits<T>::min(); (*swap)(a,b);
          a = numeric_limits<T>::min(); b = numeric_limits<T>::min(); (*swap)(a,b);
        }
        
        int main() {
          letsTest<char>(swap1);
          letsTest<bool>(swap1);
          letsTest<short>(swap1);
          letsTest<int>(swap1);
          letsTest<long>(swap1);
          letsTest<long long>(swap1);
          letsTest<unsigned short>(swap1);
          letsTest<unsigned int>(swap1);
          letsTest<unsigned long>(swap1);
          letsTest<unsigned long long>(swap1);
          letsTest<float>(swap1);
          letsTest<double>(swap1);
          letsTest<long double>(swap1);
        
          letsTest<char>(swap2);
          letsTest<bool>(swap2);
          letsTest<short>(swap2);
          letsTest<int>(swap2);
          letsTest<long>(swap2);
          letsTest<long long>(swap2);
          letsTest<unsigned short>(swap2);
          letsTest<unsigned int>(swap2);
          letsTest<unsigned long>(swap2);
          letsTest<unsigned long long>(swap2);
        }
        

        Les cas erronés (résumé : le premier swap ne marche pas sur les bool et tous les flottants) :

        swap+ type=b avant A=1 B=1 après A=1 B=0
        swap+ type=b avant A=1 B=1 après A=1 B=0
        swap+ type=b avant A=1 B=1 après A=1 B=0
        swap+ type=f avant A=3.40282e+38 B=42 après A=0 B=3.40282e+38
        swap+ type=f avant A=1.17549e-38 B=42 après A=42 B=0
        swap+ type=f avant A=3.40282e+38 B=3.40282e+38 après A=-nan B=inf
        swap+ type=f avant A=1.17549e-38 B=3.40282e+38 après A=3.40282e+38 B=0
        swap+ type=f avant A=3.40282e+38 B=1.17549e-38 après A=0 B=3.40282e+38
        swap+ type=d avant A=1.79769e+308 B=42 après A=0 B=1.79769e+308
        swap+ type=d avant A=2.22507e-308 B=42 après A=42 B=0
        swap+ type=d avant A=1.79769e+308 B=1.79769e+308 après A=-nan B=inf
        swap+ type=d avant A=2.22507e-308 B=1.79769e+308 après A=1.79769e+308 B=0
        swap+ type=d avant A=1.79769e+308 B=2.22507e-308 après A=0 B=1.79769e+308
        swap+ type=e avant A=1.18973e+4932 B=42 après A=0 B=1.18973e+4932
        swap+ type=e avant A=3.3621e-4932 B=42 après A=42 B=0
        swap+ type=e avant A=1.18973e+4932 B=1.18973e+4932 après A=-nan B=inf
        swap+ type=e avant A=3.3621e-4932 B=1.18973e+4932 après A=1.18973e+4932 B=0
        swap+ type=e avant A=1.18973e+4932 B=3.3621e-4932 après A=0 B=1.18973e+4932

        Et le second swap ne marche pas sur les flottants.

        • [^] # Re: Autre méthode

          Posté par (page perso) . Évalué à 2.

          Merci pour ce petit test très instructif. Et j'ai testé chez moi, car j'avoue ne pas comprendre les échecs du second swap étant donné que cette méthode fait une totale abstraction de la signification des données (seule la représentation en mémoire compte) : et chez moi, ça marche ! J'ai testé avec Visual Studio 2010 (oui, je sais, c'est mal :-D)

          Sinon, pour le premier swap, rien d'anormal à mes yeux concernant les flottants (à cause des erreurs d'arrondis) ni dans le cas des booléens (je suis d'ailleurs étonné qu'on puisse faire des additions / soustractions avec les booléens, j'aurais bien vu une erreur de compilation !)

          • [^] # Re: Autre méthode

            Posté par (page perso) . Évalué à 1.

            Je fais mon mea culpa, je n'ai pas vu qu'il n'y avais pas les tests pour les flottants pour la méthode utilisant swap2, car bien entendu, cela ne compile pas. Honte à moi de ne pas l'avoir vu...

            • [^] # Re: Autre méthode

              Posté par (page perso) . Évalué à 2.

              Bon, histoire de me faire pardonner, j'ai compléter le code de précédant afin de pouvoir tenir compte des types ne disposant pas de l'opération ^ comme c'est le cas pour les flottants (en utilisant la spécialisation des templates).

              #include <iostream>
              #include <limits>
              #include <typeinfo>
              
              using namespace std;
              
              template <typename T> void swap1(T & A, T & B) {
                T oldA = A;
                T oldB = B;
                A = A + B;
                B = A - B;
                A = A - B;
                if (!((A==oldB) && (B==oldA))) {
                  cout << "swap+\ttype=" << typeid(T).name()
                   << "\tavant A=" << oldA << "\tB=" << oldB
                   << "\taprès A=" << A << "\tB=" << B << endl;
                }
              }
              
              template <typename T> void swap2(T & A, T & B) {
                T oldA = A;
                T oldB = B;
                A ^= B;
                B ^= A;
                A ^= B;
                if (!((A==oldB) && (B==oldA))) {
                  cout << "swap^\ttype=" << typeid(T).name()
                   << "\tavant A=" << oldA << "\tB=" << oldB
                   << "\taprès A=" << A << "\tB=" << B << endl;
                }
              }
              
              template <typename T, int I> 
              struct SwapContainer {
              	static void swap3(T & A, T & B) {
              	  T oldA = A;
              	  T oldB = B;
              	  int8_t* rA = (int8_t*)&A;
              	  int8_t* rB = (int8_t*)&B;
              	  
              	  for (int i = 0; i < I; ++i)
              	  {
              		  *rA ^= *rB;
              		  *rB ^= *rA;
              		  *rA ^= *rB;
              		  rA++;
              		  rB++;
              	  }
              	  
              	  if (!((A==oldB) && (B==oldA))) {
              		cout << "swap^\ttype=" << typeid(T).name()
              		 << "\tavant A=" << oldA << "\tB=" << oldB
              		 << "\taprès A=" << A << "\tB=" << B << endl;
              	  }
              	}
              };
              
              template <typename T> 
              struct SwapContainer<T, 4> {
              	static void swap3(T & A, T & B) {
              	  T oldA = A;
              	  T oldB = B;
              	  int32_t & rA = *(int32_t*)&A;
              	  int32_t & rB = *(int32_t*)&B;
              	  
              	  rA ^= rB;
              	  rB ^= rA;
              	  rA ^= rB;
              	  
              	  if (!((A==oldB) && (B==oldA))) {
              		cout << "swap^\ttype=" << typeid(T).name()
              		 << "\tavant A=" << oldA << "\tB=" << oldB
              		 << "\taprès A=" << A << "\tB=" << B << endl;
              	  }
              	}
              };
              
              template <typename T> 
              struct SwapContainer<T, 8> {
              	static void swap3(T & A, T & B) {
              	  T oldA = A;
              	  T oldB = B;
              	  int64_t & rA = *(int64_t*)&A;
              	  int64_t & rB = *(int64_t*)&B;
              	  
              	  rA ^= rB;
              	  rB ^= rA;
              	  rA ^= rB;
              	  
              	  if (!((A==oldB) && (B==oldA))) {
              		cout << "swap^\ttype=" << typeid(T).name()
              		 << "\tavant A=" << oldA << "\tB=" << oldB
              		 << "\taprès A=" << A << "\tB=" << B << endl;
              	  }
              	}
              };
              
              template <> void swap2<float>(float & A, float & B) {
                SwapContainer< float, sizeof(float) >::swap3(A, B);
              }
              
              template <> void swap2<double>(double & A, double & B) {
                SwapContainer< double, sizeof(double) >::swap3(A, B);
              }
              
              template <> void swap2<long double>(long double & A, long double & B) {
                SwapContainer< long double, sizeof(long double) >::swap3(A, B);
              }
              
              template <typename T> void letsTest(void (*swap)(T&, T&)) {
                T a;
                T b;
              
                a = 42; b = 69; (*swap)(a,b);
                a = numeric_limits<T>::max(); b = 42; (*swap)(a,b);
                a = numeric_limits<T>::min(); b = 42; (*swap)(a,b);
                a = numeric_limits<T>::max(); b = numeric_limits<T>::max(); (*swap)(a,b);
                a = numeric_limits<T>::min(); b = numeric_limits<T>::max(); (*swap)(a,b);
                a = numeric_limits<T>::max(); b = numeric_limits<T>::min(); (*swap)(a,b);
                a = numeric_limits<T>::min(); b = numeric_limits<T>::min(); (*swap)(a,b);
              }
              
              int main() {
              /*
                letsTest<char>(swap1);
                letsTest<bool>(swap1);
                letsTest<short>(swap1);
                letsTest<int>(swap1);
                letsTest<long>(swap1);
                letsTest<long long>(swap1);
                letsTest<unsigned short>(swap1);
                letsTest<unsigned int>(swap1);
                letsTest<unsigned long>(swap1);
                letsTest<unsigned long long>(swap1);
                letsTest<float>(swap1);
                letsTest<double>(swap1);
                letsTest<long double>(swap1);
              */
                letsTest<char>(swap2);
                letsTest<bool>(swap2);
                letsTest<short>(swap2);
                letsTest<int>(swap2);
                letsTest<long>(swap2);
                letsTest<long long>(swap2);
                letsTest<unsigned short>(swap2);
                letsTest<unsigned int>(swap2);
                letsTest<unsigned long>(swap2);
                letsTest<unsigned long long>(swap2);
                letsTest<float>(swap2);
                letsTest<double>(swap2);
                letsTest<long double>(swap2);
              }
              

              Bon, l'implémentation par défaut de swap3 est améliorable d'un point de vue des performances, mais l'idée principale est là :-)

              A noter la présence de 2 spécialisations partielles afin d'optimiser le swap.

        • [^] # Re: Autre méthode

          Posté par (page perso) . Évalué à 3.

          Les cas erronés (résumé : le premier swap ne marche pas sur les bool et tous les flottants) :

          Le calcul sur flottants est toujours un calcul avec erreurs qui dépend de beaucoup de choses et en particulier des calculs déjà faits: c'est à dire que deux calculs identiques peuvent donner des résultats distincts (mais probablement pas très distincts). En gros pour les flottants, on peut presque considérer que le test d'égalité teste l'égalité physique.

      • [^] # Re: Autre méthode

        Posté par (page perso) . Évalué à 4.

        Joli. En plus cela supprime les problèmes éventuels de débordement.

        Cette solution est effectivement bien supérieure à celle de Delahaye, outre la disparition des problèmes de débordement, elle présente comme avantage de marcher avec toutes les valeurs: on échange par ce moyen les contenus de deux registres.

        Cette solution est très classique, on la trouve dans plusieurs manuels de programmation assembleur, comme la très basique introduction de la collection Marabout.

        Pour résumer le texte de Delahaye semble, d'après l'idée qu'en donne le résumé qui en est fait, expliquer plutôt mal une astuce bien connue. :P

        • [^] # Re: Autre méthode

          Posté par (page perso) . Évalué à 2.

          on échange par ce moyen les contenus de deux registres

          Quand on en a seulement la possibilité. Avec des types entiers, pas de problème, mais avec des types flottants ? On peut bien calculer leur longueur, puis itérer sur les char correspondants, mais c'est déjà plus compliqué…

          • [^] # Re: Autre méthode

            Posté par . Évalué à 1.

            Avec des types entiers, pas de problème, mais avec des types flottants ?

            Note que tu peux caster ton flottant en entier (tout flottant a une représentation entière correspondante) puis faire l'échange avec la représentation entière.

            Bon, tout ça me parait totalement dépourvu d'intérêt en pratique car "la réduction de l'utilisation mémoire": c'est du pipeau, pas besoin de stocker la variable temporaire en mémoire, un registre suffit..

            • [^] # Re: Autre méthode

              Posté par (page perso) . Évalué à 2.

              Bon, tout ça me parait totalement dépourvu d'intérêt en pratique car "la réduction de l'utilisation mémoire": c'est du pipeau, pas besoin de stocker la variable temporaire en mémoire, un registre suffit..

              Un registre suffit à condition d'en avoir un sous la main, or ils sont une ressource rare sur les architectures x86: cette astuce y est parfaitement utile.

          • [^] # Re: Autre méthode

            Posté par . Évalué à 3.

            Il est représenté sur combien de bits ton nombre flottants ? Pour un float du C, il tiens dans le registre de processeurs 32bits donc pas de problème. Pour les doubles, les abstractions du C font que tu n'a pas de problème (il va faire ça en utilisant 2 paires de registres au lieu d'un si tu n'utilise pas de registres 64 bits). Dans tout les autres cas, il est probablement plus intéressant de passer par des pointeurs/références.

            Les logiciels sous licence GPL forcent leurs utilisateurs à respecter la GPL (et oui, l'eau, ça mouille).

            • [^] # Re: Autre méthode

              Posté par (page perso) . Évalué à 5.

              C'est pire que cela en fait, cf le bug 323 ouvert depuis 11 ans chez GCC, et qui va le rester, le flottant peut passer par les registres plus précis de la FPU aussi...

              #include <iostream>
              
              double foo(unsigned nb) {
                      double sum = 0.9;
                      for (unsigned i=0; i<nb;++i) sum+=0.1;
                      return sum;
              }
              
              int main() {
                      double diff = 1.0 - foo(1);
                      std::cout << diff << std::endl;
              }
              

              Résultat attendu : 0 (c'est le cas en GCC 4.4)
              Résultat obtenu : -2.77556e-17 (GCC 2.95 à 4.0 au moins, sur x86)

              Palliatifs : déclarer sum comme volatile et utiliser -ffloat-store (Do not store floating point variables in registers, and inhibit other options that might change whether a floating point value is taken from a register or memory.)

              Codage en binaire (IEEE float 32 bits, double 64 bits, long double 80 bits), prenons le cas des float par exemple :

              • 1.0 = (-1)^0 . 2^(127-127) . (1.00000000000000000000000)
              • 0.1 ~ (-1)^0 . 2^(123-127) . (1.10011001100110011001101...)
              • 0.9 ~ (-1)^0 . 2^(126-127) . (1.11001100110011001100110...)

              Le problème rencontré est dû à la précision excessive dans l'unité de calcul en virgule flottante (FPU). Les calculs en interne sont plus précis que les résultats renvoyés.

              • [^] # Re: Autre méthode

                Posté par . Évalué à 2.

                on s'approche de problèmes qui sont du genre :

                • 3*(1/3) = 1
                • 3*3.33333... = 9.9999...

                Non ?

                Les logiciels sous licence GPL forcent leurs utilisateurs à respecter la GPL (et oui, l'eau, ça mouille).

                • [^] # Re: Autre méthode

                  Posté par (page perso) . Évalué à 5.

                  La subtilité c'est que l'arrondi peut avoir lieu à des précisions différentes suivant là où il est effectué, le CPU faisant les calculs sur 64 bits en double, alors que la FPU les fait sur 80 (donc à chaque passage de l'un à l'autre, y a apparition/disparition de précision). Et que l'endroit où est effectué l'arrondi dépend des optimisations du compilateur, donc des options de compilation (et du compilateur).

                  Bref cela peut amener au contre-intuitif (A+B) != (A+B) suivant qui fait l'addition. Et je parle bien de dire que (1/3+1/3+1/3) != (1/3+1/3+1/3), et pas de (1/3+1/3+1/3) != 1 qui n'est pas surprenant en calcul flottant.

                  • [^] # Re: Autre méthode

                    Posté par . Évalué à 4.

                    Bref cela peut amener au contre-intuitif (A+B) != (A+B) suivant qui fait l'addition. Et je parle bien de dire que (1/3+1/3+1/3) != (1/3+1/3+1/3), et pas de (1/3+1/3+1/3) != 1 qui n'est pas surprenant en calcul flottant.

                    En informatique oui, pour les mathématiciens …

                    Les logiciels sous licence GPL forcent leurs utilisateurs à respecter la GPL (et oui, l'eau, ça mouille).

                  • [^] # Re: Autre méthode

                    Posté par . Évalué à 1.

                    Bref cela peut amener au contre-intuitif (A+B) != (A+B) suivant qui fait l'addition.

                    par deux méthodes différentes, donc bon...

                    • [^] # Re: Autre méthode

                      Posté par (page perso) . Évalué à 3.

                      Par deux unités de calcul différentes. D'un côté une addition sur 64 bits, de l'autre une addition sur 80 bits dont le résultat est ensuite tronqué/arrondi sur 64 bits. Disons que quand on sait ce qui se passe, c'est logique, mais que spontanément on ne pense pas forcément en premier lieu qu'il y a des calculs avec surprécision dans l'unité de FPU...

                      • [^] # Re: Autre méthode

                        Posté par . Évalué à 10.

                        Second principe du calcul numérique : ne jamais, mais alors jamais, pas question, même pas y penser, même pas en rêve, comparer deux flottants par égalité directe. C’est une aberration de la nature qu’il faut éradiquer sans pitié de l’Univers. Vérifier que leur différence absolue est inférieure à un ε fixé, lui-même supérieur à la précision numérique.

                        • [^] # Re: Autre méthode

                          Posté par . Évalué à 2.

                          Et le premier, c'est quoi ?

                          • [^] # Re: Autre méthode

                            Posté par (page perso) . Évalué à 3.

                            Ne pas utiliser un Pentium

                            « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

                            • [^] # Re: Autre méthode

                              Posté par . Évalué à 1.

                              « Le résultat est faux. » L’histoire sur le Pentium, bien que marrante :), n’en n’est qu’un corollaire.

        • [^] # Re: Autre méthode

          Posté par (page perso) . Évalué à 2.

          Le texte de Delahaye est beaucoup plus général que ça il s'intéresse aux divers calculs possible sans utilisation de mémoire auxiliaire. (Application linéaire si je me souvient bien)

          • [^] # Re: Autre méthode

            Posté par (page perso) . Évalué à 2.

            Le texte du journal évoque des applications au calcul matriciel: dans ce cas je ne vois pas très bien d'une part l'intérêt d'échanger le contenu de deux matrices plutôt que d'échanger les matrices elle-mêmes (style échange de références), d'autre part l'intérêt d'une méthode semblable à celle décrite dans l'article. En effet, en calcul numérique il faut éviter d'ajouter des nombres d'ordre de grandeur différents car on perd beaucoup de précision dans ces calculs.

    • [^] # Pendant ce temps, en Python...

      Posté par . Évalué à 4.

      a, b = b, a

      • [^] # Re: Pendant ce temps, en Python...

        Posté par . Évalué à 2.

        Quelqu'un pour nous le faire en lisp?

      • [^] # Re: Pendant ce temps, en Python...

        Posté par . Évalué à 10.

        Et surtout ne pas comprendre comment ça marche ?

        Les logiciels sous licence GPL forcent leurs utilisateurs à respecter la GPL (et oui, l'eau, ça mouille).

        • [^] # Re: Pendant ce temps, en Python...

          Posté par . Évalué à 2.

          Certainement pas, je n'ai pas dit ça...

          Mais le fait est que l'échange du contenu de deux variables est une opération tellement courante qu'il est regrettable, à mon avis, que la plupart des langages ne l'implémentent pas en standard.

          On pourrait difficilement nier que l'exemple que je cite en Python est clair (lisible) et concis (quand on le compare aux exemples en C++ plus haut).

          Mais je suis d'accord avec toi: il est certain que cette simplicité syntaxique ne doit pas cacher la sémantique qui est derrière: par exemple, il est utile savoir si, dans ce cas particulier de l'affectation multiple, l'interpréteur évalue les valeurs de la partie droite de l'affectation ou se effectue un simple échange(*) de pointeurs sans évaluer ces valeurs.

          (*) Lequel échange, à son tour, se fera in fine avec ou sans utilisation d'un registre temporaire selon que le processeur a ou non dans son jeu d'instructions une opération de type "swap".

          • [^] # Re: Pendant ce temps, en Python...

            Posté par . Évalué à 2.

            (*) Lequel échange, à son tour, se fera in fine avec ou sans utilisation d'un registre temporaire selon que le processeur a ou non dans son jeu d'instructions une opération de type "swap".

            Tu vois que c'est bien de comprendre, le code que j'ai donné montre qu'il n'est jamais nécessaire d'avoir une instruction particulière pour effectuer le swap, du moment que la CPU a une instruction XOR (il y en a qui n'en ont pas ?).

            D'ailleurs comment fait l'interpréteur pour utiliser la bonne instruction si elle existe ?

            Les logiciels sous licence GPL forcent leurs utilisateurs à respecter la GPL (et oui, l'eau, ça mouille).

          • [^] # Re: Pendant ce temps, en Python...

            Posté par . Évalué à 3.

            On pourrait difficilement nier que l'exemple que je cite en Python est clair (lisible) et concis (quand on le compare aux exemples en C++ plus haut).

            En c++ :

            std::swap(a, b);
            

            me paraît plus explicite. C'est un comble que le C++ soit plus explicite que le python ;)

            Étienne

    • [^] # Re: Autre méthode

      Posté par (page perso) . Évalué à 2.

      La permutation devrait être une instruction du langage, pas une fonction:

      https://secure.wikimedia.org/wikipedia/en/wiki/Std::swap#Dedicated_instructions

      http://devnewton.bci.im

      • [^] # Re: Autre méthode

        Posté par . Évalué à 1.

        Pas convaincu, je ne sais pas si on s'éloigne pas des architectures RISC. De plus sur le marché un nombre non négligeables de CPU n'ont pas ce genre d'instructions et il faut une solution de contournement logiciel pour les gérer.

        Les logiciels sous licence GPL forcent leurs utilisateurs à respecter la GPL (et oui, l'eau, ça mouille).

        • [^] # Re: Autre méthode

          Posté par . Évalué à 2.

          je ne sais pas si on s'éloigne pas des architectures RISC

          C'est petit joueur l'instruction de swap, si tu veux du lourd, c'est l'instruction qui fait un CRC : http://byteworm.com/2010/10/13/crc32/. Ça c'est du CISC et du lourd.

          Étienne

        • [^] # Re: Autre méthode

          Posté par . Évalué à 2.

          Bah, l'instruction swap est utilisée aussi sur certains CPU (exemple : ARM) pour réaliser des opération de lecture/écriture de RAM atomique (gestion de sémaphores) en environnement multiprocesseurs.

  • # OpenSilicium

    Posté par (page perso) . Évalué à 7.

    À noter aussi dans les kiosques, le troisième numéro de OpenSilicium, un magazine lancé par Diamond Editions (qui fait aussi GNU/Linux Magazine France, Linux Pratique, Misc, etc.). OpenSilicium est consacré à tout ce qui est électronique, embarqué, bas niveau. Et le troisième numéro confirme tout à fait les deux premiers: un magazine vraiment passionnant pour ceux qui s'intéressent à ces thématiques. Je le recommande vivement.

  • # Linux Identity

    Posté par . Évalué à 2.

    Linux Identity propose deux éditions suivantes :

    *Linux Identity Collection - Linux Starter Kit
    http://www.linuxidentity.com/index.php?name=News&file=article&sid=96

    *Linux Identity Kit - The Best of Linux
    http://www.linuxidentity.com/index.php?name=News&file=article&sid=97

  • # L'ont-ils fait exprès ?

    Posté par . Évalué à 10.

    « Menaces sur le Web : Tim Berners‐Lee, son créateur, s’inquiète », Pour la Science № 404

    Article Quarante-Deux : Toute personne dépassant un kilomètre de haut doit quitter le Tribunal. -- Le Roi de Cœur

  • # Un peu déçu.

    Posté par . Évalué à 6.

    Ce midi, j'ai enfin réussi à acheter ce Hors série de GNU/Linux (après avoir fait environ 5 maisons de la presse), et j'ai lu les quelques premières pages. Je dois le dire, j'ai été plutôt déçu ! Le contenu était intéressant, certes, mais ces quelques pages étaient bourrées de fautes d'orthographe et de grammaire. J'espère vraiment que les articles suivants seront de meilleure qualité.

    Enfin bon, voila, tout ça pour dire qu'un relecteur n'aurait pas été de trop ...

    • [^] # Re: Un peu déçu.

      Posté par (page perso) . Évalué à 3.

      Mea culpa, mea maxima culpa !
      Des étapes de relectures nous avons, mais pour ce dernier numéro, en raison de conditions particulières et ponctuelles, nous avons commis l'erreur de sauter une étape de relecture. Généralement la passion pour la technique étant inversement proportionnelle au niveau ortho-grammatical de certains sujets (moi inclus (en fait, surtout moi)) c'était clairement une mauvaise idée.
      Le process est maintenant rétabli et tout est rentré dans l'ordre, les personnes en charge de la relecture souffrent et pestent à nouveau comme précédemment.
      Toutes nos excuses pour le filtre temporairement désactivé.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.