Rechercher
 

Manipulation des types entiers

Compilation Les opérateurs ++ et --



Accès rapide :
   La vidéo
   Déclaration de variables
   Les types numériques entiers
   Les différentes bases numériques
   Groupage de chiffres
   Constantes de type long
   Operateurs arithmétiques sur entiers
   Operateurs de comparaisons

La vidéo

Cette vidéo vous montre comment déclarer des variables et comment utiliser les différents types entiers en Java (byte, short, int et long). Les syntaxes relatives aux différentes bases numériques sont étudiées ainsi qu'une première série d'opérateurs relatifs à la manipulation d'entiers.


Manipulation des types entiers en Java

Déclaration de variables

Un programme manipule souvent un très grand nombre de données. Ces données sont chargées en mémoire à différentes adresses. Une adresse mémoire correspond au numéro de case mémoire à partir duquel la donnée associée est stockée. Si vous deviez programmer en langage assembleur, vous auriez la responsabilité de manipuler ces adresses mémoires (une adresse différente pour chaque donnée). Si on imagine que votre programme occupe 1Go (un giga octets) alors ces adresses seraient comprises entre 0 et 1 000 000 000, vous comprendrez alors aisément que l'exercice risque d'être compliqué.

C'est pour cela qu'on a inventé la notion de variable. Une variable est associée à une adresse mémoire, mais ce n'est plus vous qui gérerez cet aspect, ce sera le compilateur Java. Une variable possède un nom, ce qui sera beaucoup plus facile à utiliser et à mémoriser. A condition, bien sûr, que vous ayez donné un nom pertinent à votre variable.

Du plus, en Java, une variable sera associée à un type de données (une catégorie de données). Cela sous-entend que votre variable occupera un nombre d'octets bien précis en mémoire. Par exemple, un entier de type int occupe 4 octets en mémoire.

Pour déclarer une variable, il faut d'abord préciser son type, puis son nom et terminer cette déclaration par un caractère ;. On peut aussi directement initialiser cette variable pour lui donner une valeur initiale : dans ce cas, affecter la valeur initiale à la variable en utilisant le caractère = juste avant le ;. Voici quelques exemples de déclaration de variables.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
public class Demo {
    public static void main( String [] args ) {
    
        int counter = 10;       // Déclare une variable entière nommée counter et initialisée à 10
        String name = "Jean";   // Déclare une variable de type chaîne de caractères appelée name
        double pi;              // Déclare une variable flottante appelée pi et non initialisée
        
        pi = 3.1415;            // On change la valeur de pi
        
        System.out.println( counter );
        System.out.println( name );
        System.out.println( pi );
        
    }
}
Fichier Demo.java : exemple de déclarations de variables
l'instruction System.out.println( variable ); permet d'afficher sur la console le contenu d'une variable. Voici le résultat produit par ce programme.
10
Jean
3.1415

Il est aussi possible de déclarer plusieurs variables sur une même ligne de déclaration. Dans ce cas, elles auront toutes le même type de données. Voici un petit exemple déclarant deux variables entières nommées x et y.

 1 
int x=10, y=15;
Fichier Demo.java : exemple de déclarations de variables

Il existe de très nombreux types de données en Java. Il est même possible de définir vos propres types de données avec, entre autre, la notion de classes. Nous commencerons, dans ce chapitre, à parler des types numériques entiers.

Les types numériques entiers

Les quatre types entiers en Java

Il existe quatre types entiers en Java, à l'instar des langages C et C++ dont Java s'inspire. C'est quatre types entiers sont : byte, short, int et long. La différence entre ces quatre types de données réside dans le nombre d'octets utilisé par la variable comme le montre le tableau ci-dessous.

  byte short int long
Taille (bits) 8 16 32 64
Etendue des valeurs -128 .. 127 -32768 .. 32767 -231 .. 231-1 -263 .. 263-1
contrairement au langage C, le type le plus petit, occupant un seul octet, n'est pas char mais bien byte. La raison en est simple : le contrôle de typage du compilateur Java est plus strict qu'en C et du coup il y a une distinction en le type entier sur un octet (byte) et le type caractère (char). Sémantiquement c'est plus propre.
de même, contrairement au langage C, il n'existe pas en Java de type entier non signé. La conséquence directe de ce choix est que les deux mots clés signed et unsigned, réservés en C, n'existent pas en Java. Tout type entier est obligatoirement signé, ce qui veut dire qu'on pourra manipuler des valeurs négatives, nulles ou positives pour chacun de ces quatre types. A mon sens, ce point-là est dommage : j'aurais apprécié de pouvoir plus fortement typer mes variables en interdisant, dans certains situations, les valeurs négatives, mais bon ...

Bien entendu, si vous cherchez à stocker une valeur trop grande, en rapport au type utilisé, dans une variable, une erreur de compilation sera produite. C'est ce que montre l'exemple ci-dessous.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
public class Demo {

    public static void main( String [] args ) {
    
        byte c = 1024;              // Valeur maximale autorisée : 127
        short s = 100000;           // Valeur maximale autorisée : 32767
        
    }

}
Exemple de code ne compilant pas, car dépassement de valeurs autorisées.

Voici le résultat de la compilation de ce programme.

$> javac Demo.java 
Demo.java:4: error: incompatible types: possible lossy conversion from int to byte
        byte c = 1024;
                 ^
Demo.java:5: error: incompatible types: possible lossy conversion from int to short
    short s = 100000;
              ^
2 errors
$>

Passage d'un type à un autre

Imaginons que vous cherchiez à transférer la valeur d'une variable entière dans une autre variable entière. Dans ce cas, il y a deux possibilités :

Un opérateur de transtypage s'introduit en mettant le type de destination entre parenthèses, comme le montre l'exemple suivant.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
public class Demo {

    public static void main( String [] args ) {
    
        byte c = 10;
        short s = c;        // Autorisé, car taille byte < taille short
        System.out.println( s );    // Affiche 10
        
        long l = 10;        // Ici, on demande explicitement de réduire la taille de la donnée
        int i = (int) l;    // de 8 octets vers 4 octets, via l'opérateur de transtypage (int) 
        System.out.println( i );    // Affiche 10
        
        i = 200000;
        s = (short) i;              // Attention, il va y avoir une perte d'information !
        System.out.println( s );    // Affiche 3392, car un short ne peut pas dépasser 32767
         
    }

}
Exemples d'utilisations d'opérateurs de transtypages

Les différentes bases numériques

Java permet d'utiliser plusieurs bases numériques pour exprimer vos valeurs entières. Il y en a trois qui sont reprises du langage C : base octale, base décimale et base hexadécimale. Depuis Java SE 7.0, une quatrième base, la base binaire, a été rajoutée au langage.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
public class Demo {

    public static void main( String [] args ) {
         
        int       binaryValue = 0b10;     // == 2
        int        octalValue = 010;      // == 8
        int      decimalValue = 10;
        int  hexadecimalValue = 0x10;     // == 16
         
        System.out.println( binaryValue );
        System.out.println( octalValue );
        System.out.println( decimalValue );
        System.out.println( hexadecimalValue );

        hexadecimalValue = 0xff;          // On change la valeur : 255 en décimal
        System.out.println( hexadecimalValue );

    }
 
}
Fichier Demo.java : les différentes bases numériques
méfiez-vous de la base octale, j'ai déjà vu des personnes ajouter des 0 devant une valeur numérique pour aligner en colonne des déclarations de variables et contrairement à ce que ces personnes pensaient, les valeurs affectées ne sont pas celles attendues si on ne connait ce point de syntaxe.

Groupage de chiffres

Depuis Java SE 7.0, il est possible d'utiliser le caractère _ pour grouper les digits (les chiffres) d'une valeur numérique. Vous pouvez grouper vos chiffres par blocs de taille quelconque. Vous n'êtes même pas obligé de définir de groupes de tailles identiques : cela peut, par exemple, s'avérer très pratique avec l'utilisation du binaire dans le cadre de la communication avec un matériel électronique.

Il est possible d'utiliser le groupage de chiffres, quelle que soit la base numérique utilisées. Voici quelques exemples d'utilisations.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
public class Demo {

    public static void main( String [] args ) {
    
        int counter = 1_000_000_000;  // Imaginez-vous compter les 0 en l'abscence du groupage.
        System.out.println( counter );
        
        int color = 0xff_ff_00_ff;    // Un beau fuchsia exprimé en codage ARGB pour Android.
        System.out.println( color );
    
        int binaryValue = 0b00000000_11111111_01010101_10101010;    // Bits groupés par octet.
        System.out.println( binaryValue );
        
    }
}
Fichier Demo.java : utilisation du groupage de chiffres
le groupage n'intervient uniquement que pour la spécification de la valeur. A l'affichage, aucun groupage n'est réalisé par défaut. Voici le résultat produit par l'exemple précédent. La valeur négative vient du faire que le type int est signé (le bit 32 étant fixé à 1, la valeur est affichée négativement).
1000000000
-65281
16733610

Pour réaliser un groupage à l'affichage, il est nécessaire d'utiliser un formateur, comme le montre l'exemple suivant. La ligne commençant par import correspond à une importation de la librairie java.text.NumberFormat.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
import java.text.NumberFormat;
            
public class Demo {

    public static void main( String [] args ) {
    
        int counter = 1_000_000_000;
        NumberFormat formatter = NumberFormat.getIntegerInstance();
        System.out.println( formatter.format( counter ) );
    
    }
}
Fichier Demo.java : formatage d'un entier à l'affichage
si vous utilisez une version de Java inférieur à Java 7.0, le groupage ne sera pas supporté. Une erreur de compilation sera produite.

Constantes de type long

Analysons le programme qui suit : qu'en pensez-vous ?

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
public class Demo {

    public static void main( String [] args ) {
    
        long counter = 10_000_000_000;
        System.out.println( counter );
        
    }
}
Fichier Demo.java : dépassement d'intervalle

En fait, ce programme ne compile pas. La raison est un peu subtile. La ligne long counter = 10_000_000_000; s'exécute en deux temps. Dans un premier temps, le compilateur vérifie la valeur entière 10_000_000_000. Or pour le compilateur, par défaut, une valeur entière est typée int : du coup 10 milliard est une valeur en dehors des bornes autorisées (-2^31 à 2^31-1). Le message affiché par le compilateur est le suivant.

$> javac Demo.java 
Demo.java:5: error: integer number too large: 10000000000
        long counter = 10_000_000_000;
                       ^
1 error
$>

Pour régler ce problème, il suffit de saisir dans le code Java une valeur entière typée long. Cela se réalise en ajoutant un caractère L à la fin de la valeur. Ce caractère L (L pour long) peut être saisi en minuscule ou bien en majuscule. Notez néanmoins que le l (en minuscule) peut être confondu avec un 1. Je vous conseille donc d'utiliser une majuscule. Voici un code qui compile parfaitement.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
public class Demo {

    public static void main( String [] args ) {
    
        long counter = 10_000_000_000L;
        System.out.println( counter );
        
    }
}
Fichier Demo.java : dépassement d'intervalle corrigé

Dans un second temps, cette valeur typée long est stockée dans la variable counter elle-même type long, donc tout va bien. Notez bien que le fait de typer la variable n'impose pas ce type à la définition de la valeur. Ca peut paraitre surprenant, mais c'est comme ça.

vous ne pouvez pas mettre un underscore (_) entre le dernier chiffre de la valeur numérique et le caractère L. Un underscore doit forcément être placé entre deux chiffres. Le caractère L n'est pas considéré comme un caractère de chiffre.

Operateurs arithmétiques sur entiers

Les opérateurs arithmétiques

Bien entendu, vous pouvez utiliser vos variables pour faire des calculs. Pour ce faire, vous disposez d'opérateurs arithmétiques : +, -, *, / et % pour, respectivement, l'addition, la soustraction, la multiplication, la division et le calcul du reste de la division entière. Voici un petit exemple.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
public class Demo {

    public static void main( String [] args ) {
    
        int firstValue = 11;
        int secondValue = 3;
        int div = firstValue / secondValue;
        int rest = firstValue % secondValue;
    
        int computedValue = div * secondValue + rest;
    
        System.out.println( "11 / 3 == " + div );                      // Affiche 3
        System.out.println( "11 % 3 == " + rest );                     // Affiche 2
        System.out.println( "computedValue == " + computedValue );     // Affiche 11

    }
}
Fichier Demo.java : exemples d'utilisation d'opérateur arithmétiques

Des règles de priorités existent entre les opérateurs. Bien entendu la multiplication (ou la division) est prioritaire par rapport à l'addition (ou la soustraction). Dans l'exemple précédent, il n'est donc pas nécessaire de forcer sur la priorité de la multiplication en utilisant des parenthèses : c'est implicite. En cas de priorités identiques, les opérateurs proposés sont évalués de la gauche vers la droite.

Si vous avez le moindre doute sur la priorité d'évaluation de vos opérateurs, utilisez les parenthèses pour forcer les priorités. Voici un exemple, mais j'insiste bien sur le fait qu'ici ce n'est pas nécessaire.

 1 
int computedValue = ( div * secondValue ) + rest;
On force la priorité

Dépassement d'étendues

L'ajout de deux variables de type byte produit un entier typé int. La raison est qu'on peut très facilement dépasser de l'étendue du type byte étant donné le peu de place occupé. Il est donc nécessaire de transtyper le résultat en byte si c'est ce que vous souhaitez récupérer. Il en va de même pour les autres opérateurs arithmétiques (soustraction, ...). Dans le même ordre d'idée, l'addition de deux short produit aussi un résultat typé int. L'exemple ci-dessous vous montre comment réaliser les transtypages (conversions vers le type souhaité).
 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
public class Demo {

    public static void main( String [] args ) {
         
        byte b1 = 10;
        byte b2 = 20;
        byte res = (byte) ( b1 + b2 );      // Transtypage en byte
        
        System.out.println( res );
        
    }
 
}
Fichier Demo.java : exemples de transtypages
Le transtypage ne permet pas toutes les transformations de types imaginables. Par exemple, il faudra trouver d'autres moyens de faire pour transformer une chaîne de caractères en numérique. Par exemple: int i = Integer.parseInt("10");.

Cas de la division entière

Le langage Java défini, comme en C, deux sortes d'opérateurs de division : vous avez la possibilité de faire des divisions entières ou des divisions flottantes. Dans l'exemple ci-dessous, il n'y a aucun doute à avoir, on divise deux entiers et on demande à récupérer un entier : la division sera donc entière.

 1 
int res = 1 / 3;   // res vaut 0, car division entière
Exemple d'une division entière

Par contre, cet exemple est plus sournois. A votre avis, quel est le résultat affiché, en sachant que le type double représente un flottant en double précision ?

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
public class Demo {

    public static void main( String [] args ) {
   
        double res = 1 / 3;
        System.out.println( res );
    
    }

}
Autre exemple d'une division entière

Même si pour la majorité des débutants Java que j'ai pu sonder sur cette question répondent 0.3333333, et bien ce n'est pas la bonne réponse. Le résultat affiché sera 0.0. Mais pourquoi ? En faire, le compilateur va d'abord évaluer la partie droite : il y voit deux entiers divisés entre eux : cela suffit à trancher et à choisir une division de type entière. Le résultat vaudra donc l'entier 0. Ensuite le compilateur s'aperçoit qu'il doit stocker cette valeur dans une variable typée double et donc il affecte 0.0, le transtypage étant ici implicite.

Opérateurs de comparaisons

Vous pouvez aussi comparer vos entiers. Pour ce faire, six opérateurs vous sont proposés : l'égalité (opérateur ==), la différence (opérateur !=), l'infériorité (opérateur <=), l'infériorité stricte (opérateur <), la supériorité (opérateur >=), la supériorité stricte (opérateur >). Voici un exemple d'utilisation.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
public class Demo {

    public static void main( String [] args ) {
    
        int numerator1 = 1;
        int denominator1 = 3;
        
        int numerator2 = 2;
        int denominator2 = 1;  
 
        int leftPart = numerator1 * denominator2;
        int rightPart = denominator1 * numerator2;
        
        if ( leftPart == rightPart ) {
            System.out.println( "Les fractions sont équivalentes" );
        } else if ( leftPart < rightPart ) {
            System.out.println( "La première fraction est plus petite" );
        } else {
            System.out.println( "La première fraction est plus grande" );
        }
    
    }
    
}
Comparaison de valeurs entières
l'instruction if permet de réaliser un test. Dans l'exemple ci-dessous trois cas peuvent être considérés. Bien entendu, étant donné les valeurs des fractions, l'affichage produit sera « La première fraction est plus petite ».


Compilation Les opérateurs ++ et --