
math
Les nombres : arrondis, racines, trigonométrie, logarithmes et hasard.
La bibliothèque math travaille sur les nombres. En Brass, tous les nombres sont du même genre (des nombres à virgule flottante sur 64 bits, comme 2, -0.5 ou 1e6) : il n'y a pas de type entier à part. math.floor(7 / 2) donne 3, et 3 s'affiche sans virgule.
Vous vous en servirez pour transformer des mesures en valeurs propres (math.floor, math.round), pour garder une valeur entre deux bornes (math.min et math.max), pour calculer des angles et des distances pour un véhicule ou un dessin (math.sqrt, math.atan2, math.sin), et pour lancer des dés (math.random).
local stock = 1234
local piles = math.floor(stock / 64)
local reste = stock % 64
print(piles .. " piles et " .. reste .. " objets")19 piles et 18 objets
Deux opérateurs remplacent souvent un appel : a // b vaut math.floor(a / b), et a % b est le reste, jamais négatif quand b est positif. Les deux sont plus rapides qu'un appel de fonction.
math.floor(x) | Arrondit vers le bas, vers moins l'infini. |
math.ceil(x) | Arrondit vers le haut, vers plus l'infini. |
math.round(x) | Arrondit à l'entier le plus proche. Les moitiés montent : 2.5 donne 3 et -2.5 donne -2. |
math.abs(x) | La valeur absolue : la distance entre x et zéro. |
math.min(...) | Le plus petit des nombres donnés. Il en faut au moins un. |
math.max(...) | Le plus grand des nombres donnés. Il en faut au moins un. |
math.huge | L'infini : plus grand que tous les autres nombres. -math.huge est plus petit que tous. |
math.sqrt(x) | La racine carrée. Celle d'un nombre négatif n'est pas un nombre : elle s'affiche nan. |
math.exp(x) | e puissance x. Utile pour des courbes douces, comme une valeur qui diminue un peu à chaque tick. |
math.log(x [, base]) | Le logarithme de x : la puissance à laquelle il faut élever la base pour obtenir x. Sans base, c'est le logarithme népérien. |
math.pi | Le nombre π, un demi-tour en radians. |
math.sin(x) | Le sinus d'un angle en radians. |
math.cos(x) | Le cosinus d'un angle en radians. |
math.tan(x) | La tangente d'un angle en radians : la pente d'une droite qui fait cet angle. |
math.atan(y [, x]) | L'arc tangente : l'angle dont la tangente vaut y / x. Avec deux arguments, elle fait exactement comme math.atan2. |
math.atan2(y, x) | L'angle de la direction qui va de l'origine au point (x, y), en radians. Contrairement à math.atan(y / x), elle sait dans quel quart se trouve le point, et ne plante pas quand x vaut zéro. |
math.fmod(a, b) | Le reste de la division de a par b, qui garde le signe de a. L'opérateur % diffère pour les nombres négatifs : son résultat a le signe de b. |
math.random([m [, n]]) | Un nombre aléatoire. Trois formes : |
math.randomseed(seed) | Relance la suite aléatoire à partir de seed : la même graine donne toujours les mêmes nombres ensuite. |
Arrondis
Arrondit vers le bas, vers moins l'infini.
xnumber- n'importe quel nombre
- number
- le plus grand nombre entier qui ne dépasse pas
x
print(math.floor(2.9))
print(math.floor(-2.1))
print(7 // 2)2 -3 3
Servez-vous-en pour découper une valeur en parts entières, par exemple un nombre d'objets en piles, ou une coordonnée en pixels en case de caractère :
local px = 137
local colonne = math.floor((px - 1) / 6) + 1 -- un caractère fait 6 pixels de large
print("le pixel " .. px .. " est dans la colonne " .. colonne)le pixel 137 est dans la colonne 23
Voir aussi math.ceil() math.round()
Arrondit vers le haut, vers plus l'infini.
xnumber- n'importe quel nombre
- number
- le plus petit nombre entier qui n'est pas en dessous de
x
math.ceil est le bon outil quand il en faut « assez » : des emplacements pour ranger des objets, des trajets de train, des lignes pour afficher une liste.
local objets = 200
print(math.ceil(objets / 64) .. " emplacements de coffre")
print(math.ceil(-2.9))4 emplacements de coffre -2
Voir aussi math.floor() math.round()
Arrondit à l'entier le plus proche. Les moitiés montent : 2.5 donne 3 et -2.5 donne -2.
xnumber- n'importe quel nombre
- number
- l'entier le plus proche
math.round est une extension de Brass (Lua n'en a pas). C'est la même chose que math.floor(x + 0.5). Pour garder une décimale, multipliez d'abord :
local vitesse = 12.3456
print(math.round(vitesse))
print(math.round(vitesse * 10) / 10)
print(math.round(-2.5))12 12.3 -2
Pour afficher un nombre avec un nombre fixe de décimales (3.10 plutôt que 3.1), utilisez string.format("%.2f", x) : il renvoie du texte, prêt à afficher.
Voir aussi math.floor() math.ceil()
La valeur absolue : la distance entre x et zéro.
xnumber- n'importe quel nombre
- number
xsans son signe
Pratique pour comparer deux valeurs sans se soucier de laquelle est la plus grande, par exemple pour savoir si une machine est assez près de sa cible :
local cible, position = 64, 61.5
if math.abs(cible - position) < 3 then
print("assez près")
end
print(math.abs(-7))assez près 7
Bornes
Le plus petit des nombres donnés. Il en faut au moins un.
xnumber- un ou plusieurs nombres
- number
- le plus petit d'entre eux
print(math.min(4, 2, 8))
local carburant = 30
print("brûle " .. math.min(carburant, 16) .. " ce tour-ci")2 brûle 16 ce tour-ci
Avec math.max, il borne une valeur entre deux limites, ce dont vous aurez sans cesse besoin avec la redstone (0 à 15) et avec les vitesses de Create (-256 à 256 tr/min) :
local function borner(x, bas, haut)
return math.max(bas, math.min(haut, x))
end
print(borner(22, 0, 15))
print(borner(-4, 0, 15))
print(borner(9, 0, 15))15 0 9
Voir aussi math.max()
Le plus grand des nombres donnés. Il en faut au moins un.
xnumber- un ou plusieurs nombres
- number
- le plus grand d'entre eux
local mesures = {12, 40, 7, 33}
local pic = mesures[1]
for i = 2, #mesures do
pic = math.max(pic, mesures[i])
end
print("pic : " .. pic)pic : 40
Voir aussi math.min()
L'infini : plus grand que tous les autres nombres. -math.huge est plus petit que tous.
- number
- l'infini
C'est la valeur de départ habituelle quand on cherche le plus petit élément d'une liste : la première valeur comparée est forcément plus petite.
local distances = {48.2, 12.9, 30}
local plus_proche = math.huge
for _, d in ipairs(distances) do
if d < plus_proche then plus_proche = d end
end
print(plus_proche)
print(math.huge, -math.huge)12.9 inf -inf
Puissances et racines
La racine carrée. Celle d'un nombre négatif n'est pas un nombre : elle s'affiche nan.
xnumber- un nombre positif ou nul
- number
- la racine carrée de
x
Son usage de tous les jours : la distance entre deux points, avec Pythagore.
local function distance(x1, z1, x2, z2)
local dx, dz = x2 - x1, z2 - z1
return math.sqrt(dx * dx + dz * dz)
end
print(math.sqrt(16))
print(distance(0, 0, 30, 40))4 50
Élever à une puissance ne demande pas de fonction : 2 ^ 10 vaut 1024, et x ^ 0.5 est une autre façon d'écrire la racine carrée.
e puissance x. Utile pour des courbes douces, comme une valeur qui diminue un peu à chaque tick.
xnumber- l'exposant
- number
- e (2,718...) puissance
x
print(math.exp(0))
print(math.exp(1))1 2.718281828459
Voir aussi math.log()
Le logarithme de x : la puissance à laquelle il faut élever la base pour obtenir x. Sans base, c'est le logarithme népérien.
xnumber- un nombre plus grand que zéro
basenumber facultatif- la base du logarithme, e (2,718...) si elle est omise
- number
- le logarithme de
x
print(math.log(100, 10))
print(math.log(1024, 2))
print(math.log(math.exp(3)))2 10 3
Un logarithme compte des chiffres ou des doublements : math.floor(math.log(n, 10)) + 1 est le nombre de chiffres d'un entier n plus grand que zéro, pratique pour aligner des colonnes de nombres à l'écran.
Voir aussi math.exp()
Trigonométrie
Les angles sont en radians : un tour complet vaut 2 * math.pi. Create et les capteurs de Create Aeronautics parlent en degrés : convertissez avec degres * math.pi / 180 et radians * 180 / math.pi.
Le nombre π, un demi-tour en radians.
- number
- 3,14159...
local r = 5
print(math.pi)
print("aire : " .. math.pi * r * r)3.1415926535898 aire : 78.539816339745
Le sinus d'un angle en radians.
xnumber- un angle en radians
- number
- son sinus, entre -1 et 1
Avec math.cos, il place un point sur un cercle : la base de toute jauge ronde, de tout balayage de radar ou de tout sprite en orbite dessiné avec gfx.
local cx, cy, rayon = 100, 60, 40
for pas = 0, 3 do
local angle = pas * math.pi / 2
local x = cx + math.round(rayon * math.cos(angle))
local y = cy + math.round(rayon * math.sin(angle))
print(pas, x, y)
end0 140 60 1 100 100 2 60 60 3 100 20
Sur un écran, les deux mêmes lignes dessinent un anneau de points. Une image d'écran comme celle-ci est obtenue en exécutant le code :
gfx.clear("black")
local cx, cy = 153, 90
for degrees = 0, 359, 10 do
local a = degrees * math.pi / 180
gfx.pixel(cx + math.round(70 * math.cos(a)), cy + math.round(70 * math.sin(a)), "lime", 3)
end
gfx.line(cx, cy, cx + 70, cy, "yellow", 2)
gfx.text(4, 4, "36 POINTS SUR UN CERCLE", "white")
Voir aussi math.cos() math.pi
Le cosinus d'un angle en radians.
xnumber- un angle en radians
- number
- son cosinus, entre -1 et 1
print(math.cos(0))
print(math.cos(math.pi))1 -1
Une jauge à aiguille : l'aiguille d'un compte-tours parcourt un demi-cercle, de la gauche (0 tr/min) à la droite (256 tr/min). Comme une fonction ne renvoie qu'une valeur en Brass, la pointe de l'aiguille revient dans une table :
local function aiguille(rpm)
local angle = math.pi - (rpm / 256) * math.pi
return {x = math.round(math.cos(angle) * 20), y = math.round(-math.sin(angle) * 20)}
end
local pointe = aiguille(128)
print(pointe.x, pointe.y)0 -20
Voir aussi math.sin() math.pi
La tangente d'un angle en radians : la pente d'une droite qui fait cet angle.
xnumber- un angle en radians
- number
- sa tangente
print(math.round(math.tan(math.pi / 4)))1
L'arc tangente : l'angle dont la tangente vaut y / x. Avec deux arguments, elle fait exactement comme math.atan2.
ynumber- la partie verticale, ou la pente quand
xest omis xnumber facultatif- la partie horizontale, 1 si elle est omise
- number
- un angle en radians
print(math.atan(1) * 180 / math.pi)45
Voir aussi math.atan2()
L'angle de la direction qui va de l'origine au point (x, y), en radians. Contrairement à math.atan(y / x), elle sait dans quel quart se trouve le point, et ne plante pas quand x vaut zéro.
ynumber- la partie verticale (ou l'écart en Z, sur une carte)
xnumber- la partie horizontale (ou l'écart en X)
- number
- l'angle du point (x, y), entre -π et π
C'est la fonction du « de quel côté tourner ? » : la direction d'un véhicule vers sa cible.
local function cap(deX, deZ, versX, versZ)
local radians = math.atan2(versZ - deZ, versX - deX)
return math.round(radians * 180 / math.pi)
end
print(cap(0, 0, 10, 0))
print(cap(0, 0, 0, 10))
print(cap(0, 0, -10, 0))0 90 180
Voir aussi math.atan()
Restes
Le reste de la division de a par b, qui garde le signe de a. L'opérateur % diffère pour les nombres négatifs : son résultat a le signe de b.
anumber- le nombre à diviser
bnumber- le diviseur
- number
- le reste de
a / b, du signe dea
print(math.fmod(7, 3), 7 % 3)
print(math.fmod(-7, 3), -7 % 3)1 1 -1 2
Pour des positions qui reviennent au début (un motif qui se répète, un anneau de 16 lampes), % est en général ce qu'il vous faut, car il ne descend jamais sous zéro.
Hasard
Chaque ordinateur a son propre générateur de nombres aléatoires. Il part d'un point différent à chaque chargement du monde : deux lancements d'un programme ne tirent pas les mêmes nombres, sauf si vous appelez math.randomseed.
Un nombre aléatoire. Trois formes :
mnumber facultatif- la borne haute (avec un argument) ou la borne basse (avec deux)
nnumber facultatif- la borne haute
- number
- un nombre aléatoire
| appel | résultat |
|---|---|
math.random() | un nombre à virgule, de 0 inclus à 1 exclu |
math.random(m) | un entier de 1 à m, les deux inclus |
math.random(m, n) | un entier de m à n, les deux inclus |
Les bornes à virgule sont arrondies vers le bas. Quand la borne basse dépasse la borne haute, le programme s'arrête avec l'erreur bad argument to 'random' (interval is empty).
print(math.random(1, 6)) -- un dé : 1, 2, 3, 4, 5 ou 6
print(math.random(10)) -- de 1 à 10
print(math.random()) -- par exemple 0.71828...Choisir un élément d'une liste au hasard :
local disques = {"cat", "blocks", "chirp", "far", "mall"}
local choix = disques[math.random(#disques)]
print("on joue : " .. choix)Une chance en pourcentage, pour un évènement qui doit arriver une fois sur cinq :
if math.random() < 0.2 then
print("un creeper apparaît !")
endVoir aussi math.randomseed()
math.randomseed(seed)
Relance la suite aléatoire à partir de seed : la même graine donne toujours les mêmes nombres ensuite.
seednumber- n'importe quel nombre
Une graine fixe donne un monde ou une énigme « au hasard » mais identique à chaque fois ; l'heure donne une nouvelle suite à chaque lancement :
math.randomseed(42)
local a = math.random(1000)
math.randomseed(42)
local b = math.random(1000)
print(a == b)true
math.randomseed(os.time() + os.id() * 1000) -- différent sur chaque ordinateur et à chaque lancementMotifs courants
Passer d'une échelle à une autre. Un signal de redstone (0 à 15) en vitesse (0 à 256 tr/min), ou un stock (0 à la capacité) en largeur de barre à l'écran :
local function convertir(valeur, deBas, deHaut, versBas, versHaut)
local t = (valeur - deBas) / (deHaut - deBas)
return versBas + t * (versHaut - versBas)
end
print(convertir(15, 0, 15, 0, 256))
print(math.floor(convertir(750, 0, 2000, 0, 40)))256 15
Lisser une mesure qui saute. Les capteurs bougent à chaque tick ; une moyenne glissante cache le bruit. Chaque nouvelle mesure compte pour 20 % du résultat :
local lisse = 0
for _, mesure in ipairs({10, 12, 30, 11, 10}) do
lisse = lisse + (mesure - lisse) * 0.2
end
print(math.round(lisse * 10) / 10)9.6
Voir aussi math.random()