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.
- As constantes
math.pi,math.eemath.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 doround(2.5). - Contas de inteiros: fatorial, MDC, MMC, combinações.
- Logaritmos, ângulos (em radianos!) e distâncias.
- Por que
0.1 + 0.2 == 0.3dáFalse, e omath.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ão7. - 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ão3.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 umfloatdê 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. O2 ** 10faz 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ção | Faz | 2.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
sumsoma: 24. - math.fabs(-7)
- O valor absoluto, em
float. Oabs()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, emath.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 deu1.2246467991473532e-16. Oe-16quer 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
Truese a diferença for minúscula em relação ao tamanho dos números. É o jeito certo de compararfloat. - 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
floatcom cuidado extra contra esses erros. Desde o Python 3.12, o própriosum()também somafloatcom mais cuidado (por isso os dois deram1.0); num Python mais antigo,sum([0.1] * 10)dá0.9999999999999999.
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
| Conta | Com math | Sem math | Qual usar |
|---|---|---|---|
| Raiz quadrada | math.sqrt(x) | x ** 0.5 | math.sqrt: mais claro (e avisa se x for negativo) |
| Potência | math.pow(2, 10) → 1024.0 | 2 ** 10 → 1024 | **: exato com inteiros |
| Valor absoluto | math.fabs(-7) → 7.0 | abs(-7) → 7 | abs: embutido e mantém o tipo |
| Cortar as decimais | math.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 cima | math.ceil(a / b) | -(-a // b) | math.ceil: o truque sem math ninguém entende |
Quando dá errado
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.
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).
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.
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)).
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.
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).
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
| Escrita | O que faz | Exemplo |
|---|---|---|
math.pi, math.e, math.tau | π, e, 2π | 3.141592653589793 |
math.inf | Infinito | math.inf > 10**100 → True |
math.sqrt(x) | Raiz quadrada (square root) | math.sqrt(49) → 7.0 |
math.isqrt(n) | Raiz quadrada inteira | math.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 float | math.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); embutido | round(2.5) → 2 |
math.factorial(n) | Fatorial | math.factorial(5) → 120 |
math.gcd(a, b) / math.lcm(a, b) | MDC / MMC | math.gcd(12, 18) → 6 |
math.comb(n, k) / math.perm(n, k) | Combinações / arranjos | math.comb(6, 2) → 15 |
math.prod(lista) | Multiplica todos os itens | math.prod([2, 3, 4]) → 24 |
math.log(x), math.log(x, base) | Logaritmo natural / numa base | math.log(8, 2) → 3.0 |
math.log10(x), math.log2(x) | Logaritmo na base 10 / 2 | math.log10(1000) → 3.0 |
math.exp(x) | e elevado a x | math.exp(1) → 2.718281828459045 |
math.sin(x), cos, tan | Seno, cosseno, tangente (em radianos) | math.sin(math.radians(30)) |
math.radians(g) / math.degrees(r) | Graus → radianos / radianos → graus | math.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 pontos | math.dist((0, 0), (3, 4)) → 5.0 |
math.isclose(a, b) | Compara float com tolerância | math.isclose(0.1 + 0.2, 0.3) → True |
math.fsum(lista) | Soma de float com precisão extra | math.fsum([0.1] * 10) → 1.0 |
| Mensagem | Causa provável |
|---|---|
ValueError: expected a nonnegative input, got -9.0 (3.13: math domain error) | Raiz de número negativo |
ValueError: expected a positive input | Logaritmo de zero ou de negativo |
TypeError: must be real number, not str | Texto (do input, de um arquivo) no lugar de número: converta |
ValueError: factorial() not defined for negative values | Fatorial de negativo |
TypeError: 'float' object cannot be interpreted as an integer | Função que só aceita int recebeu float |
OverflowError: math range error | Resultado maior do que um float aguenta |
Seno de 30 dá -0.988… | Ângulo em graus: converta com math.radians |
== entre float dá False inesperado | Use math.isclose |
Exercícios
1. A raiz
Complete para mostrar a raiz quadrada de 144:
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 mathtraz a calculadora científica:math.pi,math.sqrt,math.ceil…- Raiz quadrada:
math.sqrt(x)(semprefloat); potência: prefira o**. - Para cima:
math.ceil("quantas caixas preciso"); para baixo:math.floor; cortando:math.truncouint. roundleva 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.