division by zero — Como Resolver em Zig
O Que Este Erro Significa
O erro division by zero é um panic de runtime que ocorre quando uma operação de divisão (/) ou módulo (%) tem zero como divisor. Em Zig, essa verificação é feita automaticamente em builds Debug e ReleaseSafe. Divisão por zero é matematicamente indefinida e, em hardware, geralmente causa uma exceção do processador.
Causas Comuns
1. Divisor Literal ou Variável com Valor Zero
pub fn main() void {
const a: u32 = 100;
const b: u32 = 0;
const resultado = a / b; // PANIC: division by zero
_ = resultado;
}
2. Módulo (Resto) com Divisor Zero
pub fn main() void {
const a: u32 = 10;
const b: u32 = 0;
const resto = a % b; // PANIC: division by zero (também se aplica a %)
_ = resto;
}
3. Resultado de Cálculo que Resulta em Zero
pub fn main() void {
const x: u32 = 5;
const y: u32 = 5;
const divisor = x - y; // divisor é 0
const resultado = 100 / divisor; // PANIC: division by zero
_ = resultado;
}
4. Divisor Vindo de Input Externo
const std = @import("std");
fn calcularMedia(soma: u32, quantidade: u32) u32 {
return soma / quantidade; // PANIC se quantidade == 0
}
5. Divisão em Loop com Condição Incorreta
pub fn main() void {
var divisor: u32 = 10;
while (divisor >= 0) { // u32 é sempre >= 0, loop infinito
const r = 100 / divisor; // PANIC quando divisor chega a 0
_ = r;
divisor -= 1; // Eventualmente causa overflow também
}
}
Como Corrigir
Solução 1: Verificar Antes de Dividir
const std = @import("std");
pub fn main() void {
const a: u32 = 100;
const b: u32 = 0;
if (b != 0) {
const resultado = a / b;
std.debug.print("resultado: {}\n", .{resultado});
} else {
std.debug.print("Erro: divisão por zero!\n", .{});
}
}
Solução 2: Retornar Optional
fn dividirSeguro(a: u32, b: u32) ?u32 {
if (b == 0) return null;
return a / b;
}
pub fn main() void {
const resultado = dividirSeguro(100, 0) orelse 0;
_ = resultado;
}
Solução 3: Retornar Error Union
const DivisaoError = error{DivisaoPorZero};
fn dividir(a: u32, b: u32) DivisaoError!u32 {
if (b == 0) return DivisaoError.DivisaoPorZero;
return a / b;
}
pub fn main() !void {
const resultado = try dividir(100, 5);
_ = resultado;
}
Solução 4: Usar Valor Padrão
fn calcularMedia(soma: u32, quantidade: u32) u32 {
if (quantidade == 0) return 0; // Ou outro valor padrão
return soma / quantidade;
}
Solução 5: Usar @max Para Garantir Mínimo
fn dividirComMinimo(a: u32, b: u32) u32 {
return a / @max(b, 1); // Garante que divisor é pelo menos 1
}
Solução 6: Validar Input do Usuário
const std = @import("std");
fn lerDivisor(reader: anytype) !u32 {
// Lê e valida o divisor
const line = try reader.readUntilDelimiter(&buf, '\n');
const valor = try std.fmt.parseInt(u32, line, 10);
if (valor == 0) return error.DivisorZero;
return valor;
}
Divisão por Zero em Comptime
Em tempo de compilação, divisão por zero é sempre um erro:
const resultado = 10 / 0; // ERRO DE COMPILAÇÃO: division by zero
Isso é detectado mesmo em builds ReleaseFast.
Divisão de Ponto Flutuante
Para tipos float, divisão por zero não causa panic — segue o padrão IEEE 754:
pub fn main() void {
const a: f64 = 1.0;
const b: f64 = 0.0;
const resultado = a / b; // resultado é +inf (infinito)
const resultado2 = -a / b; // resultado2 é -inf
const resultado3 = b / b; // resultado3 é NaN
_ = resultado;
_ = resultado2;
_ = resultado3;
}
Use std.math.isNan e std.math.isInf para verificar:
const std = @import("std");
pub fn main() void {
const resultado: f64 = 0.0 / 0.0;
if (std.math.isNan(resultado)) {
std.debug.print("Resultado é NaN\n", .{});
}
}
Erros Relacionados
- integer overflow at runtime — Overflow de inteiro em runtime
- integer overflow at comptime — Overflow em compilação
- integer truncation — Truncamento de inteiro