division by zero — Como Resolver em Zig

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

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.