Create: Computing AgesDoc Brass
Bibliothèques

math

Les nombres : arrondis, racines, trigonométrie, logarithmes et hasard.

Tous les ordinateurs

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).

Brass
local stock = 1234
local piles = math.floor(stock / 64)
local reste = stock % 64
print(piles .. " piles et " .. reste .. " objets")
Écran
19 piles et 18 objets
Astuce

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.

Fonctions
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.hugeL'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.piLe 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

#

math.floor(x)

→ number

Arrondit vers le bas, vers moins l'infini.

Paramètres
x number
n'importe quel nombre
Renvoie
number
le plus grand nombre entier qui ne dépasse pas x
Brass
print(math.floor(2.9))
print(math.floor(-2.1))
print(7 // 2)
Écran
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 :

Brass
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)
Écran
le pixel 137 est dans la colonne 23

Voir aussi math.ceil() math.round()

#

math.ceil(x)

→ number

Arrondit vers le haut, vers plus l'infini.

Paramètres
x number
n'importe quel nombre
Renvoie
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.

Brass
local objets = 200
print(math.ceil(objets / 64) .. " emplacements de coffre")
print(math.ceil(-2.9))
Écran
4 emplacements de coffre
-2

Voir aussi math.floor() math.round()

#

math.round(x)

→ number

Arrondit à l'entier le plus proche. Les moitiés montent : 2.5 donne 3 et -2.5 donne -2.

Paramètres
x number
n'importe quel nombre
Renvoie
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 :

Brass
local vitesse = 12.3456
print(math.round(vitesse))
print(math.round(vitesse * 10) / 10)
print(math.round(-2.5))
Écran
12
12.3
-2
Note

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()

#

math.abs(x)

→ number

La valeur absolue : la distance entre x et zéro.

Paramètres
x number
n'importe quel nombre
Renvoie
number
x sans 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 :

Brass
local cible, position = 64, 61.5
if math.abs(cible - position) < 3 then
  print("assez près")
end
print(math.abs(-7))
Écran
assez près
7

Bornes

#

math.min(...)

→ number

Le plus petit des nombres donnés. Il en faut au moins un.

Paramètres
x number
un ou plusieurs nombres
Renvoie
number
le plus petit d'entre eux
Brass
print(math.min(4, 2, 8))
local carburant = 30
print("brûle " .. math.min(carburant, 16) .. " ce tour-ci")
Écran
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) :

Brass
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))
Écran
15
0
9

Voir aussi math.max()

#

math.max(...)

→ number

Le plus grand des nombres donnés. Il en faut au moins un.

Paramètres
x number
un ou plusieurs nombres
Renvoie
number
le plus grand d'entre eux
Brass
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)
Écran
pic : 40

Voir aussi math.min()

#

math.huge

→ numbervaleur

L'infini : plus grand que tous les autres nombres. -math.huge est plus petit que tous.

Renvoie
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.

Brass
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)
Écran
12.9
inf -inf

Puissances et racines

#

math.sqrt(x)

→ number

La racine carrée. Celle d'un nombre négatif n'est pas un nombre : elle s'affiche nan.

Paramètres
x number
un nombre positif ou nul
Renvoie
number
la racine carrée de x

Son usage de tous les jours : la distance entre deux points, avec Pythagore.

Brass
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))
Écran
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.

#

math.exp(x)

→ number

e puissance x. Utile pour des courbes douces, comme une valeur qui diminue un peu à chaque tick.

Paramètres
x number
l'exposant
Renvoie
number
e (2,718...) puissance x
Brass
print(math.exp(0))
print(math.exp(1))
Écran
1
2.718281828459

Voir aussi math.log()

#

math.log(x [, base])

→ number

Le logarithme de x : la puissance à laquelle il faut élever la base pour obtenir x. Sans base, c'est le logarithme népérien.

Paramètres
x number
un nombre plus grand que zéro
base number facultatif
la base du logarithme, e (2,718...) si elle est omise
Renvoie
number
le logarithme de x
Brass
print(math.log(100, 10))
print(math.log(1024, 2))
print(math.log(math.exp(3)))
Écran
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.

#

math.pi

→ numbervaleur

Le nombre π, un demi-tour en radians.

Renvoie
number
3,14159...
Brass
local r = 5
print(math.pi)
print("aire : " .. math.pi * r * r)
Écran
3.1415926535898
aire : 78.539816339745
#

math.sin(x)

→ number

Le sinus d'un angle en radians.

Paramètres
x number
un angle en radians
Renvoie
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.

Brass
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)
end
Écran
0   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 :

Brass
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")
Écran
Écran

Voir aussi math.cos() math.pi

#

math.cos(x)

→ number

Le cosinus d'un angle en radians.

Paramètres
x number
un angle en radians
Renvoie
number
son cosinus, entre -1 et 1
Brass
print(math.cos(0))
print(math.cos(math.pi))
Écran
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 :

Brass
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)
Écran
0   -20

Voir aussi math.sin() math.pi

#

math.tan(x)

→ number

La tangente d'un angle en radians : la pente d'une droite qui fait cet angle.

Paramètres
x number
un angle en radians
Renvoie
number
sa tangente
Brass
print(math.round(math.tan(math.pi / 4)))
Écran
1
#

math.atan(y [, x])

→ number

L'arc tangente : l'angle dont la tangente vaut y / x. Avec deux arguments, elle fait exactement comme math.atan2.

Paramètres
y number
la partie verticale, ou la pente quand x est omis
x number facultatif
la partie horizontale, 1 si elle est omise
Renvoie
number
un angle en radians
Brass
print(math.atan(1) * 180 / math.pi)
Écran
45

Voir aussi math.atan2()

#

math.atan2(y, x)

→ number

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.

Paramètres
y number
la partie verticale (ou l'écart en Z, sur une carte)
x number
la partie horizontale (ou l'écart en X)
Renvoie
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.

Brass
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))
Écran
0
90
180

Voir aussi math.atan()

Restes

#

math.fmod(a, b)

→ number

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.

Paramètres
a number
le nombre à diviser
b number
le diviseur
Renvoie
number
le reste de a / b, du signe de a
Brass
print(math.fmod(7, 3), 7 % 3)
print(math.fmod(-7, 3), -7 % 3)
Écran
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.

#

math.random([m [, n]])

→ number

Un nombre aléatoire. Trois formes :

Paramètres
m number facultatif
la borne haute (avec un argument) ou la borne basse (avec deux)
n number facultatif
la borne haute
Renvoie
number
un nombre aléatoire
appelré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).

Brass
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 :

Brass
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 :

Brass
if math.random() < 0.2 then
  print("un creeper apparaît !")
end

Voir 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.

Paramètres
seed number
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 :

Brass
math.randomseed(42)
local a = math.random(1000)
math.randomseed(42)
local b = math.random(1000)
print(a == b)
Écran
true
Brass
math.randomseed(os.time() + os.id() * 1000)  -- différent sur chaque ordinateur et à chaque lancement

Motifs 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 :

Brass
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)))
Écran
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 :

Brass
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)
Écran
9.6

Voir aussi math.random()