Introdução
Zig oferece um módulo matemático completo em std.math com funções para aritmética avançada, trigonometria, logaritmos e constantes. Diferente de muitas linguagens, Zig trata overflow e operações inválidas como erros, proporcionando mais segurança em cálculos numéricos.
Nesta receita, você aprenderá a usar as principais funções matemáticas disponíveis.
Pré-requisitos
- Zig instalado (versão 0.13+). Veja o guia de instalação
- Conhecimento básico de Zig. Consulte a introdução ao Zig
Funções Básicas
const std = @import("std");
const math = std.math;
pub fn main() !void {
// Valor absoluto
std.debug.print("abs(-42) = {d}\n", .{@abs(@as(i32, -42))});
std.debug.print("abs(-3.14) = {d:.2}\n", .{@abs(@as(f64, -3.14))});
// Mínimo e máximo
std.debug.print("max(10, 20) = {d}\n", .{@max(@as(i32, 10), @as(i32, 20))});
std.debug.print("min(10, 20) = {d}\n", .{@min(@as(i32, 10), @as(i32, 20))});
// Clamp (limitar a um intervalo)
std.debug.print("clamp(15, 0, 10) = {d}\n", .{math.clamp(@as(i32, 15), 0, 10)});
std.debug.print("clamp(-5, 0, 10) = {d}\n", .{math.clamp(@as(i32, -5), 0, 10)});
std.debug.print("clamp(5, 0, 10) = {d}\n", .{math.clamp(@as(i32, 5), 0, 10)});
}
Raiz Quadrada e Potências
const std = @import("std");
const math = std.math;
pub fn main() !void {
// Raiz quadrada
std.debug.print("sqrt(16) = {d:.1}\n", .{math.sqrt(@as(f64, 16.0))});
std.debug.print("sqrt(2) = {d:.6}\n", .{math.sqrt(@as(f64, 2.0))});
// Potência
std.debug.print("pow(2, 10) = {d:.0}\n", .{math.pow(f64, 2.0, 10.0)});
std.debug.print("pow(3, 3) = {d:.0}\n", .{math.pow(f64, 3.0, 3.0)});
// Raiz cúbica
std.debug.print("cbrt(27) = {d:.1}\n", .{math.cbrt(@as(f64, 27.0))});
// Exponencial (e^x)
std.debug.print("exp(1) = {d:.6}\n", .{math.exp(@as(f64, 1.0))});
std.debug.print("exp(2) = {d:.6}\n", .{math.exp(@as(f64, 2.0))});
}
Trigonometria
const std = @import("std");
const math = std.math;
pub fn main() !void {
const pi = math.pi;
std.debug.print("Constante pi = {d:.10}\n", .{pi});
// Graus para radianos
const graus: f64 = 45.0;
const radianos = graus * pi / 180.0;
std.debug.print("\n{d:.0}° = {d:.6} rad\n", .{ graus, radianos });
// Funções trigonométricas
std.debug.print("\nsin(45°) = {d:.6}\n", .{@sin(radianos)});
std.debug.print("cos(45°) = {d:.6}\n", .{@cos(radianos)});
std.debug.print("tan(45°) = {d:.6}\n", .{@tan(radianos)});
// Funções inversas
const valor: f64 = 0.5;
std.debug.print("\nasin({d}) = {d:.6} rad\n", .{ valor, math.asin(valor) });
std.debug.print("acos({d}) = {d:.6} rad\n", .{ valor, math.acos(valor) });
std.debug.print("atan({d}) = {d:.6} rad\n", .{ valor, math.atan(valor) });
// atan2 (ângulo de um ponto)
std.debug.print("atan2(1, 1) = {d:.6} rad ({d:.1}°)\n", .{
math.atan2(@as(f64, 1.0), @as(f64, 1.0)),
math.atan2(@as(f64, 1.0), @as(f64, 1.0)) * 180.0 / pi,
});
}
Logaritmos
const std = @import("std");
const math = std.math;
pub fn main() !void {
// Logaritmo natural (base e)
std.debug.print("ln(1) = {d:.6}\n", .{@log(@as(f64, 1.0))});
std.debug.print("ln(e) = {d:.6}\n", .{@log(@as(f64, math.e))});
std.debug.print("ln(10) = {d:.6}\n", .{@log(@as(f64, 10.0))});
// Logaritmo base 2
std.debug.print("\nlog2(8) = {d:.6}\n", .{math.log2(@as(f64, 8.0))});
std.debug.print("log2(1024) = {d:.6}\n", .{math.log2(@as(f64, 1024.0))});
// Logaritmo base 10
std.debug.print("\nlog10(100) = {d:.6}\n", .{math.log10(@as(f64, 100.0))});
std.debug.print("log10(1000) = {d:.6}\n", .{math.log10(@as(f64, 1000.0))});
// Constantes
std.debug.print("\ne = {d:.10}\n", .{math.e});
std.debug.print("pi = {d:.10}\n", .{math.pi});
std.debug.print("ln(2) = {d:.10}\n", .{math.ln2});
}
Arredondamento
const std = @import("std");
const math = std.math;
pub fn main() !void {
const valores = [_]f64{ 3.2, 3.5, 3.7, -2.3, -2.5, -2.7 };
std.debug.print("{s:>8} {s:>8} {s:>8} {s:>8}\n", .{ "Valor", "Floor", "Ceil", "Round" });
std.debug.print("{s:>8} {s:>8} {s:>8} {s:>8}\n", .{ "-----", "-----", "-----", "-----" });
for (valores) |v| {
std.debug.print("{d:>8.1} {d:>8.1} {d:>8.1} {d:>8.1}\n", .{
v,
@floor(v),
@ceil(v),
@round(v),
});
}
}
Saída esperada
Valor Floor Ceil Round
----- ----- ----- -----
3.2 3.0 4.0 3.0
3.5 3.0 4.0 4.0
3.7 3.0 4.0 4.0
-2.3 -3.0 -2.0 -2.0
-2.5 -3.0 -2.0 -2.0
-2.7 -3.0 -2.0 -3.0
Exemplo Prático: Distância entre Coordenadas
const std = @import("std");
const math = std.math;
const Coordenada = struct {
lat: f64, // graus
lon: f64, // graus
};
fn distanciaHaversine(a: Coordenada, b: Coordenada) f64 {
const R = 6371.0; // Raio da Terra em km
const to_rad = math.pi / 180.0;
const dlat = (b.lat - a.lat) * to_rad;
const dlon = (b.lon - a.lon) * to_rad;
const lat1 = a.lat * to_rad;
const lat2 = b.lat * to_rad;
const sa = @sin(dlat / 2.0);
const sb = @sin(dlon / 2.0);
const h = sa * sa + @cos(lat1) * @cos(lat2) * sb * sb;
return 2.0 * R * math.asin(math.sqrt(h));
}
pub fn main() !void {
const sao_paulo = Coordenada{ .lat = -23.5505, .lon = -46.6333 };
const rio = Coordenada{ .lat = -22.9068, .lon = -43.1729 };
const brasilia = Coordenada{ .lat = -15.7975, .lon = -47.8919 };
std.debug.print("SP -> RJ: {d:.1} km\n", .{distanciaHaversine(sao_paulo, rio)});
std.debug.print("SP -> BSB: {d:.1} km\n", .{distanciaHaversine(sao_paulo, brasilia)});
std.debug.print("RJ -> BSB: {d:.1} km\n", .{distanciaHaversine(rio, brasilia)});
}
Dicas e Boas Práticas
Use
@aspara especificar tipos: Funções destd.mathprecisam saber o tipo do argumento.Builtins vs std.math:
@sqrt,@sin,@cos,@log,@floor,@ceil,@roundsão builtins otimizados.Cuidado com NaN e Inf: Operações inválidas (como
sqrt(-1)) podem retornar NaN. Verifique commath.isNan().Precisão de float:
f64tem ~15 dígitos significativos,f32tem ~7.
Receitas Relacionadas
- Aritmética Segura (Overflow) - Overflow seguro
- Gerar Números Aleatórios - Números aleatórios
- Converter entre Bases Numéricas - Conversão de bases
- Trabalhando com Big Integers - Inteiros grandes