Gilliek
20oct/116

Une histoire de modulo …

Tout développeur connait le fameux (le seul, l'unique) : modulo

Comme je suis d'humeur narrative aujourd'hui,  je vais quand même expliquer de quoi il s'agit :-)

Cours du jour, bonjour

Bon, ouvrez bien vos oreilles yeux, on commence.

Tout le monde se souvient de sa tendre enfance, à l'école, en train d'assister à son premier cours de maths sur les divisions. Plutôt que de s'amuser à calculer le résultat réel (au sens mathématique du terme), on ne s'intéressait qu'à la partie entière et au reste.

Petits exemples :

12 / 5 = 2 et Reste = 2

6 / 2 = 3 et Reste = 0

9 / 2 = 4 et Reste = 1

9 / 3 = 3 et Reste = 0

En somme (notez le jeu de mot :-P ), une division entière.

Et bien le modulo calcule le reste. C'est un nom bien barbare, qui au final, n'est rien de plus qu'un calcul enfantin

Donc si on reprend l'exemple ci-dessus, mais en version informatique cette fois, on a :

(dans beaucoup de langage, l'opérateur du modulo est le %)

12 % 5 = 2

6 % 2 = 0

9 % 2 = 1

9 % 3 = 0

Modulo = reste de la division entière.

On utilise vraiment ça ? A quoi ça peut bien servir une telle chose ??

Et bien, c'est très souvent utilisé lorsqu'on programme. On l'utilise, entre autres nombreuses choses, pour déterminer si un nombre est

pair. Il suffit de faire nombre % 2 Si le résultat est null, donc qu'il n'y a pas de reste, alors le nombre est pair. Sinon il est impair.

Maintenant que tout le monde c'est ce qu'est le modulo, on va pouvoir poursuivre sur le sujet de ce post.

Revenons aux choses serieuses

Faisons un petit exercice. Quel est le résultat de :

-5 % 26 = ?

(bien que nous ne soyons pas directement dans post concernant le domaine de la cryptographie, je vais utiliser les deux fameux protagonistes Bob et Alice, parce que je suis tombé sur cette étrangeté pendant un Travail Pratique de cryptographie)

  • Bob : Pff facile, c'est 21 !
  • Alice : Mais, non pas du tout c'est -5 !
  • Bob : Tu n'as rien compris, un modulo c'est cyclique, ça ne peut pas être être négatif !
  • Alice : Rien du tout. Tu es HS  coco !

Mais qui a raison ? Et bien, ils ont tous les deux raisons. Avant d'en venir aux explications, regardons ce qu'en disent les langages de programmation.

Ruby :

$> ruby -e "puts -5 % 26"
21
$>

Python

$> python -c "print(-5 % 26)"
21
$>

Octave (et MATLAB)

$>octave --eval "mod(-5, 26)"
GNU Octave, version 3.4.2
Copyright (C) 2011 John W. Eaton and others.
This is free software; see the source code for copying conditions.
There is ABSOLUTELY NO WARRANTY; not even for MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  For details, type `warranty'.

Octave was configured for "x86_64-unknown-linux-gnu".

Additional information about Octave is available at http://www.octave.org.

Please contribute if you find this software useful.
For more information, visit http://www.octave.org/help-wanted.html

Read http://www.octave.org/bugs.html to learn how to submit bug reports.

For information about changes from previous versions, type `news'.

ans =  21
$>

(On peut voir Bob trépigner :-P )

Java

class Main {
    public static void main(String[] argv) {
        System.out.println("-5 % 26 = " + (-5 % 26));
    }
}
$> javac Main.java
$> java Main
-5 % 26 = -5
$>

PHP

$> php -r 'print((-5 % 26) . "n");'
-5
$>

Agné ?! (le sourire de Bob se fane ... Alice est intriguée, comme on peut s'en douter)

Java et PHP ne sont pas les seuls. C, C++ (et d'autres) retournent -5.

Mais pourquoi ?

Et bien, en réalité, il y a deux définitions du modulo !

Regardons un peu ce qu'en dit notre vieil ami Wikipedia : http://fr.wikipedia.org/wiki/Modulo_(informatique)

Dans l'article, on a les deux définitions :

  1. x mod yxy * floor(xy)
  2. xyxy * iPart(xy)

La première définition donne un modulo cyclique, càd compris entre 0 et le diviseur. Je ne connaissais que la première définission et c'est à cause de ça que je me suis énnervé sur mon Travail Pratique de cryptographie (en Java). Pour résumer, je voulais faire un décalage sur chaque caractère d'une String. Bien entendu, je veux que quand on décale, par exemple, a de -4, on ait w. J'ai donc utilisé un modulo. Et comme j'utilisais le résultat comme indice d'un tableau, j'avais un joli OutOfBoundsExceptions à cause d'un indice négatif. Après quelques tests, j'ai enfin trouvé d'où venait le problème.

C'est donc bon à savoir pour tout développeur :-)

Moralité de l'histoire : Vérifier l'évaluation du modulo du langage utilisé afin de ne pas se faire avoir bêtement (comme moi quoi :-P )

Edit : j'ai mis une liste des langages trié en fonctione de la définition utilisée là : http://blog.gilliek.ch/programmation/modulo-la-suite

6déc/100

TCPDF, ton sauveur !

Si toi aussi tu en as mare de PDFlib, TCPDF est là pour toi ;-)

En tant que développeur Web, il m'est arrivé de devoir générer des PDF. Le problème étant que la plupart des hébergeurs ne propose que la version gratuite de PDFlib qui est une horreur sans nom (grrr). Mal pensé, mal documenté (et le exemples sont en Java ...) et en plus il est très limité en sa version gratuite ... je vous laisse imaginer la galère pour développer avec ...

Mais ces mauvais moments sont terminés, parce que TCPDF est là (<3) ! En effet, avec TCPDF, pas besoin d'installer quoique ce soit sur le serveur (ce qui aurait posé problème pour de l'hébergement mutualisé), il suffit de l'uploader sur le serveur et d'inclure  ce qu'il faut (avec include, require, etc). En plus, c'est beau parce qu'on met directement du code HTML. Concernant la documentation, sur le site on trouve de beaux exemples (en PHP!) clairs et utiles.

12nov/100

PHP : Une erreur d’operateur

En PHP, on peut affecter une valeur à une variable  selon une certaine condition avec des opérateurs ternaires.

Par exemple :

On aimerait que la variable result vaille 42 si x est plus grand que y et 0 sinon. Sans les opérateurs ternaires ça donnerait ça :

if (x > y)
     result = 42;
else
     result = 0;

ça prend 4 lignes et c'est moche ! C'est là que les opérateurs ternaires interviennent. On peut réécrire avec ceux-ci le code ci-dessus de la manière suivante :

result = (x > y) ? 42 : 0;

Beaucoup plus beau, non ?

Si tout fonctionnait pour le mieux dans le meilleur des monde (dédicace à Candide de Voltaire) je n'en parlerai sans doute pas dans ce billet !

A vos consoles !

Plutôt qu'un long et interminable discours, un exemple ! Comme le laisse suggérer le titre, ouvrez une console (ou terminal) ;-)

Maintenant, exécutez-y la commande suivante (il faut avoir au préalable installé PHP) :

php -r 'print 42 > 100 ? "42 est plus grand que 100" : 42 < 100 ? "42 est plus petit que 100" : "42 est égal à 100";'

Ca marche ...

Si vous avez bien recopié la commande, vous devriez voir s'afficher :

42 est plus petit que 100

... mais pas toujours !

Maintenant, inversons l'ordre des opérations ! Saisissez donc la commande :

php -r 'print 42 < 100 ? "42 est plus petit que 100" : 42 > 100 ? "42 est plus grand que 100" : "42 est égal à 100";'

Et là vous voyer s'afficher un terrible résultat :

42 est plus grand que 100

Comme vous pouvez le constater, le résultat est faux : 42 n'est pas plus grand que 100 :-P

Je sais bien que 42 est la réponse universelle, mais faut pas abuser non plus !

Mais pourquoi ?

Il s'agit en fait d'un problème d'associativité des opérateur '?' et ':' dans PHP.  En effet, en PHP, ces deux opérateurs sont left-associative (associatif à gauche pour les non-anglophones). Et c'est le seul langage à contenir une telle abération.

Prenons Ruby (il vous faut avoir installé Ruby pour pouvoir lancer la commande, évidemment):

ruby -e 'print 42 < 100 ? "42 est plus petit que 100" : 42 > 100 ? "42 est plus grand que 100" : "42 est égal à 100"'

L'interpréteur Ruby nous sort :

42 est plus petit que 100

Que faire ?

Il y a deux solutions:

  1. A court terme : utiliser des parenthèses pour bien définir l'ordre des opérations.
  2. A long terme : Ne plus utiliser PHP :-P Bon, je sais, c'est un peu radical et parfois on n'a pas vraiment le choix :-D

Si vous voulez d'autres exemples d'absurdités de PHP, je vous recommande le site (en anglais) : http://www.steike.com/code/php-must-die/