Python math

Somar, subtrair, multiplicar e dividir o Python faz sem ajuda (aula Operadores Aritméticos). Mas e a raiz quadrada? E arredondar para cima, para saber quantas caixas de ovos a padaria precisa? E o pi, para calcular o tamanho da pizza? Para isso existe o módulo math ("matemática"): a calculadora científica do Python, que já vem instalada.

Você vai aprender
  • As constantes math.pi, math.e e math.inf.
  • Raízes: sqrt, isqrt, cbrt, e a diferença para o **.
  • A arredondar para cima, para baixo e "cortando": ceil, floor, trunc, e a surpresa do round(2.5).
  • Contas de inteiros: fatorial, MDC, MMC, combinações.
  • Logaritmos, ângulos (em radianos!) e distâncias.
  • Por que 0.1 + 0.2 == 0.3 dá False, e o math.isclose.
  • Os erros reais: raiz de negativo, logaritmo de zero, texto no lugar de número, número grande demais.

A ideia: a calculadora científica da gaveta

A calculadora comum, a do caixa da padaria, tem as quatro operações. Para as outras contas existe a calculadora científica, cheia de botões a mais: √, π, sen, log, x!. O módulo math é essa calculadora: você a pega com import math (como na aula Módulos e import) e "aperta os botões" com math.nome(…).

import math

print(math.sqrt(49))
$ python3 exemplo.py
7.0

Os nomes das funções são abreviações em inglês, as mesmas usadas nas calculadoras e em outras linguagens. A tabela da Referência rápida traz todos, com a tradução.


1. As constantes: pi, e, inf

import math

print("pi =", math.pi)
print("e =", math.e)
print("tau =", math.tau)
print("infinito:", math.inf)
print(math.inf > 10**100)
$ python3 constantes.py
pi = 3.141592653589793
e = 2.718281828459045
tau = 6.283185307179586
infinito: inf
True
math.pi
O π: quantas vezes o contorno de um círculo é maior que o diâmetro. Com 15 casas, muito mais preciso que o "3,14" da escola.
math.e
O número de Euler, a base dos logaritmos naturais (aparece em juros compostos e crescimento).
math.tau
Duas vezes o pi (uma volta completa, em radianos).
math.inf
"Infinito": maior que qualquer número. Útil como ponto de partida para achar um mínimo (menor = math.inf).

São valores, e não funções: sem parênteses. O nome todo em minúsculas, apesar de serem constantes, é uma exceção antiga do math.

Missão: a área de um círculo é π × raio². O programa usa 3.14 e erra a área da pizza. Troque pelo math.pi (lembre do import) e veja a área certa: 706.86.

raio = 15
area = 3.14 * raio ** 2
print(f"Pizza de {raio} cm de raio: {area:.2f} cm²")
import math

raio = 15
area = math.pi * raio ** 2
print(f"Pizza de {raio} cm de raio: {area:.2f} cm²")

2. Raízes e potências

import math

print(math.sqrt(49))
print(math.sqrt(2))
print(49 ** 0.5)
print(math.cbrt(27))
print(math.isqrt(50))
print(math.pow(2, 10))
print(2 ** 10)
$ python3 raizes.py
7.0
1.4142135623730951
7.0
3.0000000000000004
7
1024.0
1024
math.sqrt(49)
Raiz quadrada (square root). Sempre devolve float: 7.0, e não 7.
49 ** 0.5
A mesma raiz, sem o math: elevar a meio é tirar a raiz quadrada.
math.cbrt(27)
Raiz cúbica (cube root). Repare: 3.0000000000000004, e não 3.0. É o arredondamento interno dos números com vírgula, explicado na seção 6. Esse último algarismo depende da biblioteca de matemática do sistema: no editor do guia, que roda no navegador, a mesma conta dá 3.0. Mais um motivo para nunca esperar que um float dê um valor exato.
math.isqrt(50)
A raiz inteira (integer square root): o maior inteiro cujo quadrado cabe em 50. 7 × 7 = 49 cabe; 8 × 8 = 64 não.
math.pow(2, 10)
Potência, sempre em float. O 2 ** 10 faz a mesma conta e mantém o inteiro.
** ou math.pow?

No dia a dia, use **: não precisa de import, e com inteiros dá um inteiro exato (até para números enormes, como 2 ** 100). O math.pow converte tudo para float. Para a raiz quadrada, math.sqrt(x) deixa a intenção mais clara que x ** 0.5.


3. Arredondando: ceil, floor, trunc e round

A padaria tem 50 ovos e cada caixa leva 12. Quantas caixas a Ana precisa?

import math

ovos = 50
por_caixa = 12

print("Divisão:", ovos / por_caixa)
print("Caixas cheias:", ovos // por_caixa)
print("Caixas necessárias:", math.ceil(ovos / por_caixa))
$ python3 caixas.py
Divisão: 4.166666666666667
Caixas cheias: 4
Caixas necessárias: 5

A divisão dá 4,17. A divisão inteira (//) diz quantas caixas ficam cheias: 4. Mas sobram 2 ovos, que também precisam de caixa: são 5 caixas. "Arredondar para cima" é o math.ceil (ceiling, "teto"). Sempre que a pergunta for "quantos eu preciso para caber tudo" (caixas, ônibus, páginas), é ceil.

Os quatro jeitos de arredondar, lado a lado:

import math

for numero in [2.3, 2.7, -2.3, -2.7]:
    print(f"{numero:5}  ceil={math.ceil(numero):3}  floor={math.floor(numero):3}  trunc={math.trunc(numero):3}  round={round(numero):3}")
$ python3 arredondar.py
  2.3  ceil=  3  floor=  2  trunc=  2  round=  2
  2.7  ceil=  3  floor=  2  trunc=  2  round=  3
 -2.3  ceil= -2  floor= -3  trunc= -2  round= -2
 -2.7  ceil= -2  floor= -3  trunc= -2  round= -3
FunçãoFaz2.7 vira-2.7 vira
math.ceil(x)Para cima, rumo ao "teto" (ceiling)3-2
math.floor(x)Para baixo, rumo ao "chão" (floor)2-3
math.trunc(x)Corta as casas decimais (truncate), como o int(x)2-2
round(x)Para o inteiro mais próximo (não precisa de import)3-3

Com os negativos, a diferença aparece: "para baixo" de -2.7 é -3 (mais longe do zero), mas "cortar" -2.7 dá -2.

A surpresa do round: o 2.5 vira 2

for numero in [0.5, 1.5, 2.5, 3.5]:
    print(numero, "->", round(numero))
print(round(2.675, 2))
$ python3 round_meio.py
0.5 -> 0
1.5 -> 2
2.5 -> 2
3.5 -> 4
2.67

Na escola, o ",5" sempre sobe. No Python, quando o número está exatamente no meio, o round vai para o vizinho par: 0.5 → 0, 1.5 → 2, 2.5 → 2, 3.5 → 4. É o "arredondamento do banqueiro", usado de propósito: somando muitos valores arredondados, metade sobe e metade desce, e o erro não se acumula para um lado só.

E o round(2.675, 2), que deveria dar 2.68, deu 2.67 por outro motivo: o 2.675 guardado no computador é, na verdade, um tiquinho menor que 2.675 (seção 6). Para dinheiro, a forma mais simples é formatar na hora de mostrar (f"{valor:.2f}", aula f-strings); quando cada centavo importa, existe o módulo decimal.

Missão: a excursão da escola tem 130 alunos, e cada ônibus leva 40. O programa diz que bastam 3 ônibus, e 10 alunos ficariam para trás. Use o math.ceil para calcular certo.

alunos = 130
por_onibus = 40

print("Ônibus necessários:", alunos // por_onibus)
import math

alunos = 130
por_onibus = 40

print("Ônibus necessários:", math.ceil(alunos / por_onibus))

4. Contas com inteiros

import math

print("5! =", math.factorial(5))
print("MDC de 12 e 18:", math.gcd(12, 18))
print("MMC de 4 e 6:", math.lcm(4, 6))
print("Duplas possíveis entre 6 pessoas:", math.comb(6, 2))
print("Pódios possíveis entre 6 corredores:", math.perm(6, 3))
print("Produto:", math.prod([2, 3, 4]))
print("Valor absoluto:", math.fabs(-7), abs(-7))
$ python3 contas.py
5! = 120
MDC de 12 e 18: 6
MMC de 4 e 6: 12
Duplas possíveis entre 6 pessoas: 15
Pódios possíveis entre 6 corredores: 120
Produto: 24
Valor absoluto: 7.0 7
math.factorial(5)
Fatorial: 5 × 4 × 3 × 2 × 1 = 120. De quantas formas 5 pessoas podem fazer uma fila.
math.gcd(12, 18)
MDC, o máximo divisor comum (greatest common divisor): o maior número que divide os dois. 6.
math.lcm(4, 6)
MMC, o mínimo múltiplo comum (least common multiple). Um remédio de 4 em 4 horas e outro de 6 em 6 coincidem a cada 12 horas.
math.comb(6, 2)
Combinações: quantos grupos de 2 dá para formar com 6 pessoas, sem importar a ordem. 15 duplas.
math.perm(6, 3)
Permutações (arranjos): quantas sequências de 3 com 6 pessoas, importando a ordem (1º, 2º e 3º lugar). 120 pódios.
math.prod([2, 3, 4])
Multiplica todos os itens da lista, como o sum soma: 24.
math.fabs(-7)
O valor absoluto, em float. O abs() embutido faz o mesmo e mantém o tipo; prefira ele.

5. Logaritmos, ângulos e distâncias

Logaritmos

import math

print(math.log10(1000))
print(math.log2(1024))
print(math.log(math.e))
print(math.log(8, 2))
print(math.exp(1))
$ python3 potencias.py
3.0
10.0
1.0
3.0
2.718281828459045

O logaritmo responde "a que potência eu elevo a base para chegar neste número?". 10 elevado a 3 dá 1000: log10(1000) é 3. Na base 2, 2 elevado a 10 dá 1024. O math.log(x) sozinho usa a base e; com um segundo argumento, a base que você quiser. O exp(x) é o caminho de volta: e elevado a x. Uma aplicação do dia a dia:

import math

inicial = 1000
taxa = 0.01
meses = math.log(2) / math.log(1 + taxa)
print(f"A 1% ao mês, o dinheiro dobra em {math.ceil(meses)} meses ({meses:.2f})")
$ python3 juros.py
A 1% ao mês, o dinheiro dobra em 70 meses (69.66)

Ângulos: o Python pensa em radianos

import math

print(math.radians(180))
print(math.degrees(math.pi / 2))
print(math.sin(math.radians(30)))
print(math.cos(math.radians(60)))
print(math.sin(math.pi))
print(math.sin(30))
$ python3 angulos.py
3.141592653589793
90.0
0.49999999999999994
0.5000000000000001
1.2246467991473532e-16
-0.9880316240928618

As funções de trigonometria (sin = seno, cos = cosseno, tan = tangente) recebem o ângulo em radianos, e não em graus. Meia volta (180°) é π radianos. Por isso:

  • math.radians(graus) converte graus em radianos, e math.degrees(radianos) faz o contrário;
  • math.sin(math.radians(30)) dá o seno de 30°: 0.49999999999999994, que é 0,5 com aquele "tiquinho" de erro da seção 6;
  • math.sin(math.pi) deveria ser 0, e deu 1.2246467991473532e-16. O e-16 quer dizer "vezes 10 elevado a -16": 0,00000000000000012. Praticamente zero;
  • math.sin(30), sem converter, calcula o seno de 30 radianos (quase 5 voltas inteiras), e dá um número que não tem nada a ver com 0,5. Não dá erro: só a resposta errada.

Distâncias: hypot e dist

import math

altura = 4
distancia = 3
escada = math.hypot(altura, distancia)
print("A escada precisa ter", escada, "metros")
print(math.dist((0, 0), (3, 4)))
$ python3 escada.py
A escada precisa ter 5.0 metros
5.0

Para alcançar uma janela a 4 metros de altura, com o pé da escada a 3 metros da parede, o Pitágoras diz: √(4² + 3²) = 5. O math.hypot (de hipotenusa) faz essa conta. O math.dist é a distância entre dois pontos, cada um como uma tupla de coordenadas.


6. Números com vírgula não são exatos: math.isclose

import math

print(0.1 + 0.2)
print(0.1 + 0.2 == 0.3)
print(math.isclose(0.1 + 0.2, 0.3))
print(sum([0.1] * 10))
print(math.fsum([0.1] * 10))
$ python3 floats.py
0.30000000000000004
False
True
1.0
1.0

O computador guarda os números em binário (zeros e uns), e alguns números que são "redondos" para nós, como 0,1, viram uma dízima infinita em binário, como 1/3 vira 0,333… em decimal. Ele guarda uma aproximação muito boa, mas não exata. Na maior parte do tempo, você nem percebe. Mas, numa comparação com ==, o "tiquinho" faz diferença: 0.1 + 0.2 dá 0.30000000000000004, que não é igual a 0.3.

math.isclose(a, b)
"Estão perto o bastante?" (is close). Responde True se a diferença for minúscula em relação ao tamanho dos números. É o jeito certo de comparar float.
math.isclose(a, b, abs_tol=0.01)
Com uma tolerância que você escolhe: "diferença de até 1 centavo".
math.fsum(lista)
Uma soma de float com cuidado extra contra esses erros. Desde o Python 3.12, o próprio sum() também soma float com mais cuidado (por isso os dois deram 1.0); num Python mais antigo, sum([0.1] * 10) dá 0.9999999999999999.
Regra prática

Nunca compare dois float com ==. Use math.isclose(a, b). Com inteiros (int), o == é sempre exato e pode ser usado à vontade.


Formas diferentes de fazer a mesma conta

ContaCom mathSem mathQual usar
Raiz quadradamath.sqrt(x)x ** 0.5math.sqrt: mais claro (e avisa se x for negativo)
Potênciamath.pow(2, 10) → 1024.02 ** 10 → 1024**: exato com inteiros
Valor absolutomath.fabs(-7) → 7.0abs(-7) → 7abs: embutido e mantém o tipo
Cortar as decimaismath.trunc(2.7)int(2.7)Tanto faz; int é o mais comum
Arredondar para baixo (positivos)math.floor(a / b)a // b// para divisão de inteiros
Arredondar para cimamath.ceil(a / b)-(-a // b)math.ceil: o truque sem math ninguém entende

Quando dá errado

Raiz de número negativo: ValueError
import math

print(math.sqrt(-9))
$ python3 erro_raiz.py
Traceback (most recent call last):
  File "/home/ana/erro_raiz.py", line 3, in <module>
    print(math.sqrt(-9))
          ~~~~~~~~~^^^^
ValueError: expected a nonnegative input, got -9.0

"Erro de valor: esperava uma entrada não negativa, recebi -9.0." Nos números reais, não existe raiz quadrada de número negativo (nenhum número vezes ele mesmo dá -9). O tipo do argumento está certo (é um número); o valor é que não serve, por isso ValueError. Como consertar: confira o valor antes (if x >= 0:) ou trate o erro com try/except ValueError.

Python mais antigo

A mensagem que diz o que era esperado e o valor recebido é novidade do Python 3.14 3.14. No Python 3.13 (o do Debian 13), a raiz de negativo e o logaritmo de zero dão só ValueError: math domain error ("erro de domínio": o número está fora dos valores que a função aceita).

Logaritmo de zero
import math

print(math.log(0))
$ python3 erro_log.py
Traceback (most recent call last):
  File "/home/ana/erro_log.py", line 3, in <module>
    print(math.log(0))
          ~~~~~~~~^^^
ValueError: expected a positive input

"Esperava uma entrada positiva." Nenhuma potência de e dá zero (nem número negativo), então o logaritmo só existe para números maiores que zero. Como consertar: garanta que o valor é positivo antes de calcular.

Texto no lugar de número: TypeError
import math

lado = input("Área do quadrado: ")
print(math.sqrt(lado))
$ python3 erro_texto.py
Área do quadrado: 16
Traceback (most recent call last):
  File "/home/ana/erro_texto.py", line 4, in <module>
    print(math.sqrt(lado))
          ~~~~~~~~~^^^^^^
TypeError: must be real number, not str

"Precisa ser um número real, não str." O input() sempre devolve texto, mesmo quando a pessoa digita só algarismos (aula input()). Desta vez é TypeError: o problema é o tipo, não o valor. Como consertar: math.sqrt(float(lado)).

Fatorial de negativo, ou de float
import math

print(math.factorial(-3))
$ python3 erro_fat.py
Traceback (most recent call last):
  File "/home/ana/erro_fat.py", line 3, in <module>
    print(math.factorial(-3))
          ~~~~~~~~~~~~~~^^^^
ValueError: factorial() not defined for negative values
import math

print(math.factorial(4.0))
$ python3 erro_fat2.py
Traceback (most recent call last):
  File "/home/ana/erro_fat2.py", line 3, in <module>
    print(math.factorial(4.0))
          ~~~~~~~~~~~~~~^^^^^
TypeError: 'float' object cannot be interpreted as an integer

O fatorial só existe para inteiros a partir de zero. Com -3, "não definido para valores negativos"; com 4.0 (que é float, mesmo sendo "redondo"), "um float não pode ser interpretado como inteiro". Como consertar: passe um int: math.factorial(int(x)), se tiver certeza de que x não tem casas decimais.

Resultado grande demais: OverflowError
import math

print(math.exp(1000))
$ python3 erro_exp.py
Traceback (most recent call last):
  File "/home/ana/erro_exp.py", line 3, in <module>
    print(math.exp(1000))
          ~~~~~~~~^^^^^^
OverflowError: math range error

"Erro de transbordamento: fora do alcance." O e elevado a 1000 tem mais de 400 algarismos, e um float só vai até perto de 1,8 × 10308. Os inteiros do Python não têm esse limite (2 ** 2000 funciona), mas as funções do math trabalham com float. Como consertar: é raro no dia a dia; se acontecer, confira se a conta faz sentido (um expoente errado, por exemplo).

Comparar float com ==: o erro sem mensagem

O pior erro com números com vírgula não aparece na tela: 0.1 + 0.2 == 0.3 dá False, e um if que dependia disso simplesmente segue pelo caminho errado. Você viu na seção 6. Como consertar: math.isclose(0.1 + 0.2, 0.3).


Referência rápida

EscritaO que fazExemplo
math.pi, math.e, math.tauπ, e, 2π3.141592653589793
math.infInfinitomath.inf > 10**100 → True
math.sqrt(x)Raiz quadrada (square root)math.sqrt(49) → 7.0
math.isqrt(n)Raiz quadrada inteiramath.isqrt(50) → 7
math.cbrt(x)Raiz cúbica (cube root)math.cbrt(27) → 3.0000000000000004 (ou 3.0)
math.pow(x, y)Potência em floatmath.pow(2, 10) → 1024.0
math.ceil(x)Arredonda para cima (ceiling, teto)math.ceil(4.1) → 5
math.floor(x)Arredonda para baixo (floor, chão)math.floor(4.9) → 4
math.trunc(x)Corta as decimais (truncate)math.trunc(-2.7) → -2
round(x) / round(x, n)Mais próximo (no meio, vai para o par); embutidoround(2.5) → 2
math.factorial(n)Fatorialmath.factorial(5) → 120
math.gcd(a, b) / math.lcm(a, b)MDC / MMCmath.gcd(12, 18) → 6
math.comb(n, k) / math.perm(n, k)Combinações / arranjosmath.comb(6, 2) → 15
math.prod(lista)Multiplica todos os itensmath.prod([2, 3, 4]) → 24
math.log(x), math.log(x, base)Logaritmo natural / numa basemath.log(8, 2) → 3.0
math.log10(x), math.log2(x)Logaritmo na base 10 / 2math.log10(1000) → 3.0
math.exp(x)e elevado a xmath.exp(1) → 2.718281828459045
math.sin(x), cos, tanSeno, cosseno, tangente (em radianos)math.sin(math.radians(30))
math.radians(g) / math.degrees(r)Graus → radianos / radianos → grausmath.radians(180) → 3.14159…
math.hypot(a, b)Hipotenusa: √(a² + b²)math.hypot(4, 3) → 5.0
math.dist(p, q)Distância entre dois pontosmath.dist((0, 0), (3, 4)) → 5.0
math.isclose(a, b)Compara float com tolerânciamath.isclose(0.1 + 0.2, 0.3) → True
math.fsum(lista)Soma de float com precisão extramath.fsum([0.1] * 10) → 1.0
MensagemCausa provável
ValueError: expected a nonnegative input, got -9.0 (3.13: math domain error)Raiz de número negativo
ValueError: expected a positive inputLogaritmo de zero ou de negativo
TypeError: must be real number, not strTexto (do input, de um arquivo) no lugar de número: converta
ValueError: factorial() not defined for negative valuesFatorial de negativo
TypeError: 'float' object cannot be interpreted as an integerFunção que só aceita int recebeu float
OverflowError: math range errorResultado maior do que um float aguenta
Seno de 30 dá -0.988…Ângulo em graus: converta com math.radians
== entre float dá False inesperadoUse math.isclose

Exercícios

1. A raiz

Complete para mostrar a raiz quadrada de 144:

import math
print(math.(144))

2. Para cima

Qual o resultado de math.ceil(7.01)?

3. O arredondamento do banqueiro

Qual o resultado de round(4.5)?

4. A Ana precisa de 23 metros de fita, e cada rolo tem 5 metros. Qual conta diz quantos rolos comprar?

5. Por que math.sin(90) não dá 1?

6. Qual é o jeito certo de conferir se total (um float) vale 0.3?

Missão final: o troco

Missão: um cliente pagou R$ 1,00 por um pão de R$ 0,70, e o caixa conferiu o troco de 30 centavos com ==. Rode: ele diz que o troco está errado! Troque a comparação por math.isclose para o programa mostrar Troco certo: 0.30.

pago = 1.00
preco = 0.70
troco = pago - preco

print("Troco calculado:", troco)
if troco == 0.30:
    print(f"Troco certo: {troco:.2f}")
else:
    print("Troco errado!")
import math

pago = 1.00
preco = 0.70
troco = pago - preco

print("Troco calculado:", troco)
if math.isclose(troco, 0.30):
    print(f"Troco certo: {troco:.2f}")
else:
    print("Troco errado!")

Resumo

  • import math traz a calculadora científica: math.pi, math.sqrt, math.ceil…
  • Raiz quadrada: math.sqrt(x) (sempre float); potência: prefira o **.
  • Para cima: math.ceil ("quantas caixas preciso"); para baixo: math.floor; cortando: math.trunc ou int.
  • round leva o ",5" exato para o número par: round(2.5) é 2.
  • Fatorial, MDC, MMC, combinações: factorial, gcd, lcm, comb, perm.
  • Seno, cosseno e tangente recebem radianos: converta com math.radians.
  • Números com vírgula têm pequenos erros de arredondamento: compare com math.isclose, nunca com ==.
  • Valor fora do que a função aceita dá ValueError; tipo errado (como um texto) dá TypeError.