@intFromFloat em Zig — Referência e Exemplos

@intFromFloat em Zig

O @intFromFloat converte um valor de ponto flutuante para um tipo inteiro, truncando a parte fracionária. Diferente de conversões implícitas em C que podem gerar comportamento indefinido, o Zig torna essa conversão explícita e definida, garantindo que o programador esteja ciente da perda de precisão.

Sintaxe

@intFromFloat(valor: anytype) IntType

O tipo de retorno é inferido pelo contexto onde o resultado é usado.

O que faz

O @intFromFloat converte um valor de ponto flutuante (f16, f32, f64, f80, f128) para um tipo inteiro. A parte fracionária é truncada (arredondada em direção a zero). Se o valor estiver fora do intervalo representável pelo tipo inteiro de destino, o resultado é um comportamento de segurança ilegal (safety-checked illegal behavior) — o que em modo debug causa um panic.

Parâmetros

  • valor (anytype): Um valor de ponto flutuante a ser convertido. Deve ser um tipo float válido (f16, f32, f64, f80, f128 ou comptime_float).

Valor de retorno

Retorna o valor truncado como o tipo inteiro de destino, inferido pelo contexto. A parte fracionária é descartada.

Exemplos práticos

Exemplo 1: Conversões básicas

const std = @import("std");

test "conversão float para inteiro" {
    const a: f64 = 42.7;
    const b: f64 = -15.9;
    const c: f64 = 0.99;

    const x: i32 = @intFromFloat(a);
    const y: i32 = @intFromFloat(b);
    const z: i32 = @intFromFloat(c);

    // Truncamento: parte fracionária é descartada
    try std.testing.expect(x == 42);   // 42.7 -> 42
    try std.testing.expect(y == -15);  // -15.9 -> -15 (trunca em direção a zero)
    try std.testing.expect(z == 0);    // 0.99 -> 0
}

Exemplo 2: Conversão em cálculos gráficos

const std = @import("std");

const Ponto = struct {
    x: i32,
    y: i32,
};

fn pontoNaTela(x_mundo: f64, y_mundo: f64, escala: f64) Ponto {
    return .{
        .x = @intFromFloat(x_mundo * escala),
        .y = @intFromFloat(y_mundo * escala),
    };
}

test "conversão para coordenadas de pixel" {
    const ponto = pontoNaTela(3.7, 2.1, 100.0);
    try std.testing.expect(ponto.x == 370);
    try std.testing.expect(ponto.y == 210);
}

Exemplo 3: Arredondamento antes da conversão

const std = @import("std");

fn arredondar(valor: f64) i64 {
    // @intFromFloat trunca, então somamos 0.5 para arredondar
    if (valor >= 0) {
        return @intFromFloat(valor + 0.5);
    } else {
        return @intFromFloat(valor - 0.5);
    }
}

fn teto(valor: f64) i64 {
    const truncado: i64 = @intFromFloat(valor);
    const como_float: f64 = @floatFromInt(truncado);
    if (como_float < valor) return truncado + 1;
    return truncado;
}

test "arredondamento personalizado" {
    try std.testing.expect(arredondar(3.7) == 4);
    try std.testing.expect(arredondar(3.2) == 3);
    try std.testing.expect(arredondar(-2.6) == -3);

    try std.testing.expect(teto(3.1) == 4);
    try std.testing.expect(teto(3.0) == 3);
    try std.testing.expect(teto(-2.3) == -2);
}

Casos de uso comuns

  1. Renderização gráfica: Converter coordenadas de mundo (float) para coordenadas de pixel (inteiro).
  2. Processamento de áudio: Converter amostras de ponto flutuante (normalizadas entre -1.0 e 1.0) para valores inteiros de PCM.
  3. Física e simulação: Converter resultados de cálculos físicos para índices de grade ou posições discretas.
  4. Formatação de números: Extrair a parte inteira de um número para exibição.
  5. Quantização: Converter valores contínuos para valores discretos em processamento de sinais.

Cuidados importantes

  • Se o valor float for NaN, +Inf ou -Inf, a conversão causa panic em modo debug.
  • Se o valor truncado estiver fora do intervalo do tipo inteiro de destino, também causa panic em modo debug.
  • Em modo ReleaseFast, esses casos resultam em comportamento indefinido, assim como em C.

Builtins relacionados

Tutoriais relacionados

Continue aprendendo Zig

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