Types numériques en Golang

GolangGolangBeginner
Pratiquer maintenant

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Bienvenue, Gophers, dans ce nouveau chapitre. Dans cette section, nous allons apprendre les types numériques. Le contenu inclut les types d'entiers couramment utilisés, les types à virgule flottante, les types booléens, ainsi que les nombres complexes et la syntaxe des valeurs littérales introduite dans la version 1.13.

Points clés de connaissance :

  • Types d'entiers
  • Types à virgule flottante
  • Types booléens
  • Nombres complexes
  • Syntaxe des valeurs littérales

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL go(("Golang")) -.-> go/BasicsGroup(["Basics"]) go(("Golang")) -.-> go/FunctionsandControlFlowGroup(["Functions and Control Flow"]) go(("Golang")) -.-> go/AdvancedTopicsGroup(["Advanced Topics"]) go/BasicsGroup -.-> go/values("Values") go/BasicsGroup -.-> go/variables("Variables") go/FunctionsandControlFlowGroup -.-> go/if_else("If Else") go/AdvancedTopicsGroup -.-> go/number_parsing("Number Parsing") go/AdvancedTopicsGroup -.-> go/base64_encoding("base64 Encoding") subgraph Lab Skills go/values -.-> lab-149067{{"Types numériques en Golang"}} go/variables -.-> lab-149067{{"Types numériques en Golang"}} go/if_else -.-> lab-149067{{"Types numériques en Golang"}} go/number_parsing -.-> lab-149067{{"Types numériques en Golang"}} go/base64_encoding -.-> lab-149067{{"Types numériques en Golang"}} end

Entiers

Les entiers peuvent être largement divisés en deux catégories : les entiers non signés et les entiers signés. Les entiers signés sont les plus largement utilisés.

Non signé signifie qu'il ne peut représenter que des nombres non négatifs (0 et les nombres positifs), tandis que les nombres signés peuvent représenter à la fois des nombres négatifs et non négatifs.

Les entiers non signés peuvent être divisés en quatre tailles : 8 bits, 16 bits, 32 bits et 64 bits, représentés respectivement par uint8, uint16, uint32 et uint64. Les entiers signés correspondants sont int8, int16, int32 et int64. Le tableau suivant montre les différentes plages représentées par chaque type :

Type Description Plage
uint8 Entier non signé sur 8 bits De 0 à 255
int8 Entier signé sur 8 bits De -128 à 127
uint16 Entier non signé sur 16 bits De 0 à 65535
int16 Entier signé sur 16 bits De -32768 à 32767
uint32 Entier non signé sur 32 bits De 0 à 4294967295
int32 Entier signé sur 32 bits De -2147483648 à 2147483647
uint64 Entier non signé sur 64 bits De 0 à 18446744073709551615
int64 Entier signé sur 64 bits De -9223372036854775808 à 9223372036854775807

Prenons uint8 et int8 comme exemples. Ce sont tous deux des entiers sur 8 bits et peuvent représenter 256 valeurs. Dans le type d'entier non signé uint8, la plage qu'il peut représenter est de 0 à 255, tandis que dans le type d'entier signé int8, la plage qu'il peut représenter est de -128 à 127.

En plus des 8 types ci-dessus, il existe trois autres types d'entiers spéciaux, uint, int et uintptr, où uint et int peuvent représenter différentes plages sur différentes plateformes, et uintptr peut être utilisé pour stocker des pointeurs.

Type Plage
uint uint32 sur les systèmes 32 bits, uint64 sur les systèmes 64 bits
int int32 sur les systèmes 32 bits, int64 sur les systèmes 64 bits
uintptr Type d'entier non signé utilisé pour stocker des pointeurs

Maintenant, créons un fichier nommé integer.go pour démontrer l'utilisation des entiers :

cd ~/project
touch integer.go
package main

import (
    "fmt"
    "unsafe"
)

func main() {
    // View the type of int in the current environment
    // Declare a as the type int
    var a int
    // Use unsafe.Sizeof() to output the memory size occupied by the type
    fmt.Printf("The type int in the current environment is %d bits\n", unsafe.Sizeof(a)*8)

    var b int8 = 125
    // Use the %d placeholder in fmt.Printf to output the value of the integer
    // Use the %T placeholder in fmt.Printf to output the type of the variable
    fmt.Printf("The value of b is %d, and the type is %T\n", b, b)

    // Integer operations
    // Declare integers c and d, and calculate their sum
    c, d := 2, 3
    fmt.Printf("c + d = %d\n", c+d)
    // 10 - 5
    fmt.Printf("10 - 5 = %d\n", 10-5)
    // 8 * 10
    fmt.Printf("8 * 10 = %d\n", 8*10)
}

Après avoir exécuté le programme, nous obtenons la sortie suivante :

go run integer.go
The type int in the current environment is 64 bits
The value of b is 125, and the type is int8
c + d = 5
10 - 5 = 5
8 * 10 = 80

Explication de la sortie :

  • The type int in the current environment is 64 bits : Cette ligne montre que le type int sur le système où le code est exécuté est sur 64 bits (ou 8 octets), indiquant qu'il s'agit d'un int64. La fonction unsafe.Sizeof(a) retourne la taille de la variable a en octets, et en la multipliant par 8, on la convertit en bits. Cela signifie que le type int peut stocker des valeurs entières plus grandes.
  • The value of b is 125, and the type is int8 : Ici, nous avons déclaré une variable b de type int8 et lui avons assigné la valeur 125. La sortie confirme cela en montrant à la fois la valeur et le type de données.
  • c + d = 5, 10 - 5 = 5, 8 * 10 = 80 : Ces lignes montrent les opérations arithmétiques de base sur les entiers : addition, soustraction et multiplication. La sortie confirme les résultats corrects de ces calculs.

Dans ce fichier, la fonction unsafe.Sizeof() peut être utilisée pour obtenir le nombre d'octets occupés par le type de variable actuel. 1 octet (byte) est égal à 8 bits, donc unsafe.Sizeof()*8 peut obtenir le nombre de bits occupés par le type. À partir de la sortie, nous pouvons voir que l'environnement en ligne est sur 64 bits. Le type réel de int dans l'environnement en ligne est int64.

Nous pouvons utiliser la commande suivante dans le terminal pour déterminer l'architecture du système actuel :

dpkg --print-architecture
amd64

Nombres à virgule flottante

Les nombres à virgule flottante, également appelés nombres décimaux, peuvent être représentés en Go à l'aide de deux types de nombres à virgule flottante : float32 et float64. Le type de nombre à virgule flottante par défaut est float64.

float32 et float64 représentent des précisions différentes. La précision par défaut de float64 est supérieure à celle de float32.

La norme IEEE 754 est la norme de calcul à virgule flottante la plus largement utilisée dans les ordinateurs, et tous les CPU modernes prennent en charge cette norme. Comme dans d'autres langages de programmation, Go utilise également la norme IEEE 754 pour stocker les nombres à virgule flottante.

Nous savons qu'un octet dans un ordinateur peut stocker 8 bits. float32 est un nombre à virgule flottante à simple précision et occupe 4 octets, soit 32 bits. float64 est un nombre à virgule flottante à double précision et occupe 8 octets, soit 64 bits.

Dans float32, le bit de signe occupe 1 bit, l'exposant occupe 8 bits, et les 23 bits restants sont utilisés pour représenter la mantisse.

Dans float64, le bit de signe occupe également 1 bit, l'exposant occupe 11 bits, et les 52 bits restants sont utilisés pour représenter la mantisse.

La valeur maximale que float32 peut représenter est approximativement 3,4e+38 en notation scientifique, et la valeur minimale est 1,4e-45. La valeur maximale que float64 peut représenter est approximativement 1,8e+308, et la valeur minimale est 4,9e-324. Nous pouvons voir que la plage des valeurs à virgule flottante peut aller de très petites à très grandes.

Nous pouvons utiliser la constante math.MaxFloat32 pour représenter la valeur maximale de float32. Utilisez la constante math.MaxFloat64 pour représenter la valeur maximale de float64.

Représentation des nombres à virgule flottante

Lors de l'affichage de nombres à virgule flottante, nous pouvons utiliser le marqueur %f de la fonction Printf du package fmt. Voici un exemple :

cd ~/project
touch float.go
package main

import (
    "fmt"
    "math"
)

func main() {
    // Output without exponential form
    fmt.Printf("2.333 without exponential form: %f\n", 2.333)
    fmt.Printf("Pi without exponential form: %f\n", math.Pi)
    // Use %.2f to keep two decimal places for Pi
    fmt.Printf("Pi with two decimal places: %.2f\n", math.Pi)
    fmt.Printf("The maximum value of float32: %f\n", math.MaxFloat32)
    // Exponential form
    fmt.Printf("2.333 in exponential form: %e", 2.333)
}

Exécutez la commande et vous verrez la sortie suivante.

go run float.go
2.333 without exponential form: 2.333000
Pi without exponential form: 3.141593
Pi with two decimal places: 3.14
The maximum value of float32: 340282346638528859811704183484516925440.000000
2.333 in exponential form: 2.333000e+00

Explication de la sortie :

  • 2.333 without exponential form: 2.333000 : Cela montre le nombre 2.333 imprimé à l'aide du marqueur %f. Par défaut, le marqueur %f affiche 6 chiffres après la virgule, donc 2.333 devient 2.333000.
  • Pi without exponential form: 3.141593 : Cette ligne imprime la valeur de la constante math.Pi, qui est une approximation de la constante mathématique π. Le marqueur %f l'affiche avec toute sa précision.
  • Pi with two decimal places: 3.14 : En utilisant %.2f, nous indiquons à fmt.Printf de formater le nombre avec deux chiffres après la virgule, ce qui donne 3.14. Cela est très utile lorsque vous avez besoin d'une précision spécifique pour la sortie.
  • The maximum value of float32: 340282346638528859811704183484516925440.000000 : Cela montre la valeur maximale qu'un float32 peut représenter. Notez qu'il s'agit d'un très grand nombre, et lorsqu'il est imprimé avec %f, il sera représenté avec de nombreux chiffres.
  • 2.333 in exponential form: 2.333000e+00 : Cette ligne montre comment représenter un nombre à virgule flottante en notation exponentielle (scientifique) à l'aide du marqueur %e. Le e+00 à la fin indique que nous multiplions 2.333000 par 10 à la puissance 0, ce qui donne simplement 2.333. Si l'exposant était e+02, le nombre serait multiplié par 10^2 (100), ce qui donnerait 233.3.

Types booléens

Le type bool n'a que deux valeurs possibles : true (vrai) ou false (faux), avec false comme valeur par défaut. Il présente les caractéristiques suivantes :

  • Il ne peut pas être converti en d'autres types, par exemple convertir un entier en booléen ou un booléen en entier.
  • Il ne peut pas participer aux opérations arithmétiques.

Les types booléens sont généralement utilisés en conjonction avec des opérateurs relationnels, tels que =, > et <. Créons un fichier nommé bool.go pour voir une démonstration :

cd ~/project
touch bool.go
package main

import (
    "fmt"
)

func main() {
    // Use the %t placeholder in fmt.Printf to represent a boolean value
    fmt.Printf("Is 3 equal to 2? %t\n", 3 == 2)
    fmt.Printf("Is 2 equal to 2? %t\n", 2 == 2)

    // Determine whether a and b are equal
    a, b := 1, 2
    fmt.Printf("a is %d, b is %d\n", a, b)
    if a > b {
        fmt.Println("a is greater than b")
    } else if a == b {
        fmt.Println("a is equal to b")
    } else {
        fmt.Println("b is greater than a")
    }
}

Après avoir exécuté le programme, nous obtenons la sortie suivante :

go run bool.go
Is 3 equal to 2? false
Is 2 equal to 2? true
a is 1, b is 2
b is greater than a

Explication de la sortie :

  • Is 3 equal to 2? false : L'expression 3 == 2 s'évalue à false, qui est ensuite affichée à l'aide du marqueur %t.
  • Is 2 equal to 2? true : L'expression 2 == 2 s'évalue à true, qui est ensuite affichée à l'aide du marqueur %t.
  • a is 1, b is 2 : Cette ligne affiche les valeurs assignées aux variables entières a et b.
  • b is greater than a : La structure conditionnelle if-else if-else s'évalue à a < b, soit 1 < 2 (vrai), donc la clause else est exécutée, ce qui fait que le programme affiche "b is greater than a".

Dans ce programme, nous utilisons d'abord %t dans fmt.Printf pour représenter une valeur booléenne, puis nous utilisons l'instruction if pour déterminer la relation entre deux valeurs. Dans fmt.Printf, nous pouvons utiliser le marqueur %d pour représenter un entier, le marqueur %f pour représenter un nombre à virgule flottante et le marqueur %t pour représenter une valeur booléenne.

Nombres complexes

Go dispose également de types de nombres complexes intégrés, qui peuvent être divisés en types complex64 et complex128. Dans complex64, la partie réelle et la partie imaginaire sont toutes deux sur 32 bits, tandis que dans complex128, la partie réelle et la partie imaginaire sont toutes deux sur 64 bits. Nous pouvons facilement effectuer des opérations sur les nombres complexes en Go.

Créez un fichier nommé complex.go et entrez le code suivant :

cd ~/project
touch complex.go
package main

import (
    "fmt"
)

func main() {
    // Initialize complex numbers in different ways
    c1 := complex(3, 1)
    c2 := 4 + 5i

    // Complex number operations
    c3 := c1 + c2
    c4 := c1 * c2
    // Use the real() function to obtain the real part of a complex number, and the imag() function to obtain the imaginary part of a complex number
    fmt.Printf("The real part of c1 is %v, the imaginary part is %v\n", real(c1), imag(c1))
    // %v in fmt.Printf can be used to represent complex numbers
    fmt.Printf("c1 + c2 is %v\n", c3)
    fmt.Printf("c1 * c2 is %v\n", c4)
}

Après avoir exécuté le programme, nous obtenons la sortie suivante :

go run complex.go
The real part of c1 is 3, the imaginary part is 1
c1 + c2 is (7+6i)
c1 * c2 is (7+19i)

Explication de la sortie :

  • The real part of c1 is 3, the imaginary part is 1 : La fonction real(c1) extrait la partie réelle du nombre complexe c1, qui est 3, et imag(c1) extrait la partie imaginaire de c1, qui est 1. Ces valeurs sont ensuite affichées à l'aide du marqueur %v.
  • c1 + c2 is (7+6i) : Cette ligne montre le résultat de l'addition des nombres complexes c1 et c2. c1 est défini comme 3 + 1i et c2 comme 4 + 5i. En additionnant séparément les parties réelles et imaginaires, on obtient (3 + 4) + (1 + 5)i, soit 7 + 6i.
  • c1 * c2 is (7+19i) : Cette ligne montre le résultat de la multiplication des nombres complexes c1 et c2. (3 + 1i) * (4 + 5i) est calculé comme (3*4 - 1*5) + (3*5 + 1*4)i, ce qui se simplifie en (12 - 5) + (15 + 4)i, et finalement en 7+19i.

Dans ce programme, nous démontrons comment initialiser et effectuer des opérations sur les nombres complexes à l'aide de la fonction complex et des opérateurs + et *. real() et imag() sont utilisées pour extraire respectivement la partie réelle et la partie imaginaire d'un nombre complexe. Le verbe %v dans fmt.Printf est utilisé comme marqueur général pour afficher les nombres complexes.

Syntaxe des littéraux numériques

Dans la version 1.13, Go a introduit la Numeric Literal Syntax (syntaxe des littéraux numériques). Elle définit la représentation des nombres dans différents systèmes de numération. Examinons ses règles.

  • Binaire : Ajoutez 0b avant l'entier. Par exemple, 0b101 est équivalent à 5 en décimal.
  • Octal : Ajoutez 0o ou 0O avant l'entier. Par exemple, 0o11 est équivalent à 9 en décimal.
  • Hexadécimal : Ajoutez 0x ou 0X avant l'entier. Par exemple, 0x1b est équivalent à 27 en décimal.
  • Utilisez _ pour séparer les chiffres dans l'entier. Par exemple, 0b1000_0100_0010_0001 est équivalent à 0b1000010000100001. Cela peut améliorer la lisibilité.

Démontrons cela en détail :

cd ~/project
touch literals.go
package main

import "fmt"

func main() {
    // Binary, add 0b at the beginning
    var a int = 0b101
    fmt.Printf("Binary a is %b, decimal is %d\n", a, a)

    // Octal, add 0o or 0O at the beginning
    var b int = 0o11
    fmt.Printf("Octal b is %o, decimal is %d\n", b, b)

    // Hexadecimal, add 0x or 0X at the beginning
    var c int = 0x1b
    fmt.Printf("Hexadecimal c is %x, decimal is %d\n", c, c)

    // Use separators
    d := 0b1000_0100_0010_0001
    e := 0b1000010000100001
    if d == e {
        fmt.Println("d is equal to e")
    }
}

Après avoir exécuté le programme, nous obtenons la sortie suivante :

go run literals.go
Binary a is 101, decimal is 5
Octal b is 11, decimal is 9
Hexadecimal c is 1b, decimal is 27
d is equal to e

Explication de la sortie :

  • Binary a is 101, decimal is 5 : Cette ligne montre la représentation binaire de 0b101, qui est 101, et son équivalent décimal, qui est 5. Le marqueur %b affiche la valeur binaire de a, tandis que %d affiche la représentation décimale.
  • Octal b is 11, decimal is 9 : Le nombre octal 0o11 est équivalent à 1*8^1 + 1*8^0 = 8 + 1 = 9 en décimal. Le marqueur %o affiche la représentation octale de b, et %d affiche sa valeur décimale.
  • Hexadecimal c is 1b, decimal is 27 : Le nombre hexadécimal 0x1b est équivalent à 1*16^1 + 11*16^0 = 16 + 11 = 27 en décimal. Le marqueur %x affiche la représentation hexadécimale de c, et %d affiche sa valeur décimale.
  • d is equal to e : Cela montre que le littéral binaire 0b1000_0100_0010_0001 est égal en valeur à 0b1000010000100001. Les underscores servent uniquement à améliorer la lisibilité et ne changent pas la valeur du nombre. La condition if est correctement évaluée à true.

Dans ce programme, nous avons démontré la déclaration et l'affichage de différents systèmes de numération, ainsi que l'utilisation de séparateurs. Dans fmt.Printf, nous avons utilisé différents marqueurs pour représenter différents systèmes de numération. Par exemple, %b représente le binaire et %x représente l'hexadécimal. Maîtriser ces éléments améliorera l'efficacité de la programmation.

Résumé

Revoyons ce que nous avons appris dans cette section :

  • Les entiers peuvent être divisés en entiers signés et entiers non signés.
  • Les types d'entiers par défaut int et uint ont des plages qui dépendent de la plateforme.
  • Représentation des nombres à virgule flottante.
  • Comment utiliser les nombres complexes.
  • Introduction de la syntaxe des littéraux numériques.
  • Comment utiliser différents marqueurs.

Dans cette section, nous avons expliqué et démontré les types d'entiers, les types à virgule flottante et les types booléens courants. Nous avons discuté de leur taille, de leur plage et de leur utilisation. Nous avons également introduit les nombres complexes et les constantes littérales. Les types numériques sont le pilier des programmes Go, et il est important pour les apprenants de bien les étudier.