Skip to content
This page has been auto-translated and may contain errors.View in English

Números e aritmética

Números aparecem em quase todo programa que você escreve. Um carrinho de compras soma um preço. Um jogo atualiza uma pontuação. Um script conta quantas vezes algo aconteceu. O Python oferece operadores aritméticos que funcionam como a matemática no papel, mais alguns outros que vale a pena conhecer desde o início.

Os operadores aritméticos do Python cobrem o conjunto padrão mais divisão inteira, módulo e exponenciação. Alguns comportamentos diferem de outras linguagens de formas que importam na prática: / sempre retorna um float, a divisão inteira (floor) arredonda em direção ao infinito negativo, e o módulo segue a semântica de módulo verdadeiro.

Torre numérica do Python: int (precisão arbitrária), float (IEEE 754 binary64), complex (não abordado aqui). Os operadores aritméticos seguem definições matemáticas em vez da convenção do C: // é divisão floor (em direção ao infinito negativo), % carrega o sinal do divisor, e ambos juntos satisfazem a identidade a == (a // b) * b + (a % b) para todas as entradas inteiras.

Os operadores

Os quatro operadores da matemática (+, -, *, /) funcionam exatamente como você esperaria. O Python adiciona mais três que você usará constantemente: divisão inteira, resto e exponenciação.

Os quatro operadores padrão se comportam como esperado, com uma regra notável: / sempre retorna um float, mesmo quando o resultado é um número inteiro. Os três operadores adicionais estendem o que você pode expressar sem nenhum trabalho extra.

Todos os sete operadores mapeiam para métodos dunder: + para __add__, // para __floordiv__, % para __mod__, ** para __pow__, e assim por diante. Operações mistas int/float se ampliam para float. / sempre retorna float, independentemente dos tipos dos operandos.

python
price    = 12.99
quantity = 3

print(price * quantity)   # 38.97
print(price + 2)          # 14.99
print(price - 1.00)       # 11.99
OperadorNomeExemploResultado
+Adição5 + 38
-Subtração5 - 32
*Multiplicação5 * 315
/Divisão5 / 31.6666...
//Divisão inteira5 // 31
%Resto5 % 32
**Exponenciação5 ** 3125

Divisão: / vs //

/ sempre dá o resultado decimal exato, mesmo se a resposta for um número inteiro. // dá apenas a parte inteira, cortando tudo após a vírgula. Ele não arredonda; ele corta:

/ sempre retorna um float, independentemente de as entradas serem inteiros. // retorna o piso do resultado: o maior inteiro que é menor ou igual ao resultado verdadeiro. Para números positivos é o mesmo que truncamento. Para negativos, não é:

/ é divisão verdadeira: sempre retorna float. // é divisão floor: aplica math.floor() ao quociente verdadeiro, sempre arredondando em direção ao infinito negativo em vez de em direção a zero. Isso difere de C e Java, onde a divisão inteira trunca. O benefício matemático: // e % do Python satisfazem a identidade a == (a // b) * b + (a % b) para todas as entradas inteiras, incluindo negativas. A divisão truncadora do C quebra essa identidade para negativos.

python
10 / 2     # 5.0   (sempre float, mesmo quando divide exatamente)
10 / 3     # 3.3333333333333335

10 // 3    # 3
7  // 2    # 3
-7 // 2    # -4    (arredonda em direção ao infinito negativo, não em direção a zero)

O resultado de -7 // 2 surpreende as pessoas. Você usará // principalmente com números positivos, onde isso não aparece. Mantenha no fundo da mente para quando aparecerem negativos.

O Python chama isso de divisão floor porque aplica a função matemática piso. Outras linguagens truncam em direção a zero, dando um resultado diferente para negativos. O nome // é uma dica: divida, depois aplique o piso.

// implementa floor(a / b), não truncamento. A identidade a == (a // b) * b + (a % b) vale para todas as entradas inteiras em Python. Em C e Java, onde / trunca em direção a zero, essa identidade falha para valores negativos e % atua como resto (assume o sinal do dividendo) em vez de módulo verdadeiro (assume o sinal do divisor).

O operador de resto %

% dá o que sobra após a divisão inteira. Se 10 // 3 é 3 (porque 3 cabe em 10 três vezes), então 10 % 3 é 1 (porque 3 × 3 = 9, e 10 - 9 = 1). O uso mais comum é verificar se um número é par ou ímpar.

% é o operador de módulo. A verificação par/ímpar é o uso óbvio, mas ele se generaliza para qualquer problema de ciclo ou rotação: manter um contador dentro de um intervalo, distribuir itens entre grupos, repetir uma sequência. O padrão é sempre value % limit, que retorna algo entre 0 e limit - 1.

O % do Python é módulo verdadeiro: o resultado sempre carrega o sinal do divisor. Isso difere de C e Java, onde % é um operador de resto e assume o sinal do dividendo. Em Python, -7 % 3 é 2, não -1, porque o módulo é definido como a - (a // b) * b e // arredonda em direção ao infinito negativo. Esse comportamento consistente de sinal é o que torna % confiável para ciclos e rotação com entradas negativas.

python
10 % 3    # 1
10 % 2    # 0  (divide exatamente)
10 % 7    # 3

6 % 2     # 0  (par)
7 % 2     # 1  (ímpar)

Exponenciação **

** eleva um número a uma potência. Use dois asteriscos, não o símbolo ^ (que significa outra coisa em Python):

** é exponenciação. Funciona também com floats, o que permite expressar raízes como potências fracionárias em vez de uma chamada de função separada:

** chama __pow__. Com dois operandos int retorna int; com qualquer operando float retorna float. Uma armadilha de precedência: -2 ** 2 é interpretado como -(2 ** 2) porque ** tem precedência maior que o menos unário, dando -4, não 4. Use parênteses: (-2) ** 2.

python
2 ** 10    # 1024
3 ** 3     # 27
9 ** 0.5   # 3.0  (raiz quadrada: elevar à potência de 0.5)

Precedência de operadores

O Python segue a ordem matemática padrão: exponenciação primeiro, depois multiplicação e divisão, depois adição e subtração. Quando estiver em dúvida, use parênteses. Eles deixam a intenção clara e não custam nada:

O Python segue a ordem padrão PEMDAS/BODMAS. A parte que confunde as pessoas: /, // e % compartilham o mesmo nível de precedência e avaliam da esquerda para a direita quando misturados. Parênteses são grátis; use-os sempre que a ordem não for óbvia à primeira vista:

Precedência da mais alta para a mais baixa entre operadores aritméticos: **, depois - unário, depois * / // % (esquerda para direita em precedência igual), depois + -. A interação do menos unário com ** é uma armadilha sutil: -2 ** 2 é -(2 ** 2) = -4 porque o menos unário tem precedência menor que **. Sempre coloque parênteses ao combinar negação com exponenciação.

python
2 + 3 * 4      # 14, não 20
2 ** 3 + 1     # 9,  não 512
10 - 4 / 2     # 8.0, não 3.0

(2 + 3) * 4    # 20
10 / (2 + 3)   # 2.0

Como int e float interagem

O Python tem uma regra consistente: / sempre retorna um decimal (até 4 / 22.0), e qualquer operação misturando um inteiro e um decimal dá um decimal. Quando precisar de um número inteiro, use // ou converta com int().

As regras de tipo são previsíveis: / sempre retorna float. // e % com dois inteiros retornam int. Qualquer operação misturando int e float retorna float. Isso significa que 4 / 2 é 2.0, não 2, o que importa quando você precisa de um inteiro (por exemplo, para usar como índice).

A coerção de tipos segue uma hierarquia fixa: int se amplia para float em operações mistas. / mapeia para __truediv__, que sempre retorna float. // mapeia para __floordiv__: com dois operandos int retorna int; com qualquer operando float retorna float. Essas regras são consistentes e previsíveis; a única surpresa é que / nunca retorna int, mesmo para 4 / 2.

python
4 / 2      # 2.0   (float, sempre)
4 // 2     # 2     (int)
4 + 2      # 6     (int)
4 + 2.0    # 6.0   (float)
4 * 0.5    # 2.0   (float)

Precisão de float

Há uma pegadinha que surpreende quase todo mundo em algum momento:

python
0.1 + 0.2   # 0.30000000000000004

Esse erro minúsculo não é um bug do Python. Computadores armazenam números decimais em binário, e alguns valores como 0.1 não podem ser representados exatamente. É semelhante a como 1/3 não pode ser escrito exatamente em decimal. Para a maioria dos cálculos do dia a dia, isso não importa. Para exibir dinheiro, round() ou o especificador de formato :.2f manterão a saída arrumada.

Floats em Python são IEEE 754 binary64: 64 bits com aproximadamente 15-16 dígitos decimais significativos de precisão. A imprecisão aparece porque algumas frações não podem ser representadas exatamente em binário. 0.1 + 0.2 produz 0.30000000000000004. O desvio só aparece quando você inspeciona o valor bruto; formatar com :.2f ou round() esconde isso na saída.

Para trabalho financeiro onde frações de centavo se acumulam, o Python fornece decimal.Decimal na biblioteca padrão, com aritmética exata em base 10. Isso é abordado no capítulo Módulos.

float é IEEE 754 binary64: sign × mantissa × 2^exponent com 53 bits de mantissa, dando precisão relativa de 2^-52 ≈ 2.2e-16. Qualquer fração cujo denominador tenha fatores primos diferentes de 2 (como 1/10 = 1/(2×5)) é uma fração binária não-terminante e não pode ser armazenada exatamente. O erro é pequeno, mas se acumula em aritmética repetida.

Para aritmética decimal exata, o decimal.Decimal do Python usa precisão arbitrária em base 10 internamente. Para aritmética racional exata sem nenhum arredondamento, fractions.Fraction armazena pares numerador/denominador. Ambos estão na biblioteca padrão, abordados no capítulo Módulos.

Literais numéricos legíveis

O Python permite colocar underscores em literais numéricos para tornar números grandes mais fáceis de ler. O Python os ignora completamente; eles são apenas para você:

Underscores são válidos em qualquer lugar em um literal numérico e são removidos durante o parsing sem efeito no valor. Úteis para separadores de milhar em constantes e para agrupar dígitos em literais binários ou hexadecimais:

Underscores em literais numéricos são uma característica do tokenizer: removidos durante a análise léxica com zero efeito no valor resultante. Válidos em inteiros, floats e literais com base (0xFF_FF, 0b1010_0001, 1_234.567_890). As únicas restrições: não podem aparecer no início, no fim, ou adjacentes a um ponto decimal ou marcador de expoente.

python
population  = 8_100_000_000
distance_km = 384_400
pi_approx   = 3.141_592_653

Funções embutidas úteis

abs()

abs() retorna o valor absoluto: sempre positivo, independentemente do sinal da entrada. Use quando você se importa com a distância de um número até zero, não com a direção.

abs() retorna a magnitude de um número. Funciona em inteiros e floats. Útil para cálculos de distância, margens de erro e qualquer situação em que a direção é irrelevante e você só precisa do tamanho do valor.

abs() chama __abs__ no operando. Para int e float retorna o mesmo tipo. Para complex retorna a magnitude (distância euclidiana até a origem) como float. O tipo de retorno corresponde ao tipo de entrada para números reais.

python
abs(-5)     # 5
abs(3.7)    # 3.7
abs(-0.5)   # 0.5

round()

round() arredonda para o inteiro mais próximo por padrão. Passe um segundo argumento para manter um número específico de casas decimais:

python
round(3.7)          # 4
round(3.2)          # 3
round(3.14159, 2)   # 3.14

Uma coisa que vale a pena saber: round(2.5)2, não 3. O Python arredonda para o número par mais próximo quando um valor está exatamente no meio entre duas opções.

round() usa arredondamento bancário: quando o valor está exatamente no meio, ele arredonda para o número par mais próximo em vez de sempre arredondar para cima. Isso minimiza o erro acumulado em trabalho estatístico, mas pode surpreender se você espera que 0.5 sempre arredonde para cima:

python
round(2.5)   # 2  (arredonda para o par mais próximo)
round(3.5)   # 4
round(4.5)   # 4  (não 5)
round(3.14159, 2)   # 3.14

round() implementa o arredondamento IEEE 754 round-half-to-even (arredondamento bancário): empates arredondam para o inteiro par mais próximo. Isso difere da convenção "arredondar metade para cima". Com um argumento ndigits, round() chama __round__ no objeto; tipos personalizados podem sobrescrever o comportamento de arredondamento. Nota: como floats não são exatos, "empates" como round(2.5) podem na verdade não estar exatamente em 0.5 em binário, dando resultados que parecem inconsistentes.

python
round(2.5)   # 2
round(3.5)   # 4
round(4.5)   # 4

divmod()

divmod() dá tanto o quociente quanto o resto em uma única chamada. Ele retorna um par de valores que você pode atribuir a dois nomes de uma vez:

divmod(a, b) é equivalente a (a // b, a % b), mas calculado em uma única etapa. Use-o quando precisar de ambos os valores de qualquer forma: paginação, conversão de tempo ou distribuição de itens em grupos.

divmod() chama __divmod__ no operando esquerdo. Realiza a divisão uma vez e retorna tanto o quociente floor quanto o resto módulo, evitando computação redundante de chamar // e % separadamente. O resultado satisfaz a == divmod(a, b)[0] * b + divmod(a, b)[1] com a semântica de divisão floor do Python para todas as entradas inteiras.

python
divmod(10, 3)   # (3, 1): quociente 3, resto 1
divmod(7, 2)    # (3, 1)
divmod(9, 3)    # (3, 0)

quotient, remainder = divmod(10, 3)
print(quotient)    # 3
print(remainder)   # 1

O que é essa coisa (3, 1)?

Isso é uma tupla: um par fixo de valores retornados juntos. Tuplas têm seu próprio capítulo. Por enquanto, separe os dois valores atribuindo a dois nomes de uma vez, como mostrado acima.

Na prática

Uma calculadora de gorjeta:

python
bill     = 45.50
tip_rate = 0.18
tip      = round(bill * tip_rate, 2)
total    = round(bill + tip, 2)

print(f"Bill:  ${bill}")
print(f"Tip:   ${tip}")
print(f"Total: ${total}")

round() mantém a saída parecida com dinheiro em vez de uma longa sequência de casas decimais.

Contando páginas para paginação e acompanhando o progresso como porcentagem:

python
total_items    = 153
items_per_page = 10

full_pages, leftover = divmod(total_items, items_per_page)
total_pages = (total_items + items_per_page - 1) // items_per_page

print(f"Full pages: {full_pages}, leftover: {leftover}")
print(f"Total pages needed: {total_pages}")   # 16
python
total_files     = 847
processed_files = 312

percent = round(processed_files / total_files * 100, 1)
print(f"Progress: {processed_files}/{total_files} ({percent}%)")

A fórmula de divisão com teto (n + d - 1) // d é um truque padrão com inteiros para arredondar para cima sem converter para float.

Normalização min-max e variação percentual: dois padrões que aparecem constantemente em trabalho com dados:

python
# normalização min-max: escalar um valor para o intervalo de 0.0 a 1.0
value   = 75
minimum = 0
maximum = 100

normalised = (value - minimum) / (maximum - minimum)
print(f"Normalised: {normalised:.2f}")   # 0.75

# variação percentual entre duas medições
before = 1_200
after  = 1_380

change = (after - before) / before * 100
print(f"Change: {change:.1f}%")          # 15.0%

Ambos os padrões se reduzem a uma razão: um valor relativo a um intervalo de referência ou a uma magnitude de referência. A precisão de float é suficiente para a maior parte do trabalho analítico; o erro acumulado só importa quando o cálculo encadeia dezenas de operações ou envolve valores que diferem por muitas ordens de magnitude.