std.math — Funções Matemáticas
O módulo std.math fornece funções matemáticas fundamentais, constantes, operações de aritmética segura e utilitários para trabalhar com números inteiros e de ponto flutuante. Ele é projetado para segurança — muitas operações que seriam undefined behavior em C retornam erros ou valores bem definidos no Zig.
Visão Geral
const std = @import("std");
const math = std.math;
Constantes
math.pi // 3.14159265358979...
math.e // 2.71828182845904...
math.tau // 6.28318530717958... (2*pi)
math.inf(f64) // Infinito positivo
math.nan(f64) // NaN
math.floatMin(f64) // Menor float positivo normalizado
math.floatMax(f64) // Maior float representável
math.maxInt(i32) // 2147483647
math.minInt(i32) // -2147483648
Funções Principais
Aritmética Segura
// Adição com detecção de overflow
pub fn add(comptime T: type, a: T, b: T) error{Overflow}!T
// Subtração com detecção de overflow
pub fn sub(comptime T: type, a: T, b: T) error{Overflow}!T
// Multiplicação com detecção de overflow
pub fn mul(comptime T: type, a: T, b: T) error{Overflow}!T
// Negação segura
pub fn negate(a: anytype) error{Overflow}!@TypeOf(a)
// Valor absoluto
pub fn absInt(a: anytype) error{Overflow}!@TypeOf(a)
// Casting seguro entre tipos numéricos
pub fn cast(comptime T: type, x: anytype) ?T
Funções Trigonométricas e Exponenciais
pub fn sin(x: anytype) @TypeOf(x)
pub fn cos(x: anytype) @TypeOf(x)
pub fn tan(x: anytype) @TypeOf(x)
pub fn asin(x: anytype) @TypeOf(x)
pub fn acos(x: anytype) @TypeOf(x)
pub fn atan(x: anytype) @TypeOf(x)
pub fn atan2(y: anytype, x: anytype) @TypeOf(y)
pub fn exp(x: anytype) @TypeOf(x)
pub fn exp2(x: anytype) @TypeOf(x)
pub fn log(x: anytype) @TypeOf(x)
pub fn log2(x: anytype) @TypeOf(x)
pub fn log10(x: anytype) @TypeOf(x)
pub fn sqrt(x: anytype) @TypeOf(x)
pub fn pow(comptime T: type, base: T, exp: T) T
Utilitários
pub fn min(a: anytype, b: anytype) @TypeOf(a)
pub fn max(a: anytype, b: anytype) @TypeOf(a)
pub fn clamp(val: anytype, lower: anytype, upper: anytype) @TypeOf(val)
pub fn divCeil(comptime T: type, a: T, b: T) T
pub fn divFloor(comptime T: type, a: T, b: T) T
pub fn order(a: anytype, b: anytype) Order
pub fn isNan(x: anytype) bool
pub fn isInf(x: anytype) bool
Exemplo 1: Cálculos Científicos
const std = @import("std");
const math = std.math;
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
// Constantes
try stdout.print("Pi: {d:.10}\n", .{math.pi});
try stdout.print("E: {d:.10}\n", .{math.e});
try stdout.print("Tau: {d:.10}\n", .{math.tau});
// Trigonometria
const angulo: f64 = math.pi / 4.0; // 45 graus
try stdout.print("\nÂngulo: {d:.4} rad ({d:.0} graus)\n", .{
angulo,
angulo * 180.0 / math.pi,
});
try stdout.print("sin: {d:.6}\n", .{math.sin(angulo)});
try stdout.print("cos: {d:.6}\n", .{math.cos(angulo)});
try stdout.print("tan: {d:.6}\n", .{math.tan(angulo)});
// Exponencial e logaritmo
try stdout.print("\nexp(1): {d:.6}\n", .{math.exp(@as(f64, 1.0))});
try stdout.print("ln(e): {d:.6}\n", .{math.log(math.e)});
try stdout.print("log2(8): {d:.6}\n", .{math.log2(@as(f64, 8.0))});
try stdout.print("log10(100): {d:.6}\n", .{math.log10(@as(f64, 100.0))});
try stdout.print("sqrt(2): {d:.6}\n", .{math.sqrt(@as(f64, 2.0))});
// Potência
try stdout.print("2^10: {d:.0}\n", .{math.pow(f64, 2.0, 10.0)});
}
Exemplo 2: Aritmética Segura contra Overflow
const std = @import("std");
const math = std.math;
fn somaSegura(a: i32, b: i32) !i32 {
return math.add(i32, a, b);
}
fn fatorial(n: u64) !u64 {
var resultado: u64 = 1;
var i: u64 = 2;
while (i <= n) : (i += 1) {
resultado = try math.mul(u64, resultado, i);
}
return resultado;
}
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
// Soma segura
const a = try somaSegura(100, 200);
try stdout.print("100 + 200 = {d}\n", .{a});
// Detecção de overflow
if (somaSegura(math.maxInt(i32), 1)) |_| {
try stdout.writeAll("Sem overflow (inesperado)\n");
} else |_| {
try stdout.writeAll("Overflow detectado em maxInt(i32) + 1\n");
}
// Fatorial com detecção de overflow
try stdout.writeAll("\nFatoriais:\n");
for (1..25) |n| {
if (fatorial(n)) |resultado| {
try stdout.print(" {d:>2}! = {d}\n", .{ n, resultado });
} else |_| {
try stdout.print(" {d:>2}! = overflow!\n", .{n});
break;
}
}
// Limites de tipos
try stdout.print("\nLimites:\n", .{});
try stdout.print(" i8: [{d}, {d}]\n", .{ math.minInt(i8), math.maxInt(i8) });
try stdout.print(" u8: [0, {d}]\n", .{math.maxInt(u8)});
try stdout.print(" i32: [{d}, {d}]\n", .{ math.minInt(i32), math.maxInt(i32) });
try stdout.print(" u64: [0, {d}]\n", .{math.maxInt(u64)});
}
Exemplo 3: Geometria e Vetores
const std = @import("std");
const math = std.math;
const Vec2 = struct {
x: f64,
y: f64,
fn magnitude(self: Vec2) f64 {
return math.sqrt(self.x * self.x + self.y * self.y);
}
fn normalizar(self: Vec2) Vec2 {
const mag = self.magnitude();
if (mag == 0) return self;
return .{ .x = self.x / mag, .y = self.y / mag };
}
fn distancia(a: Vec2, b: Vec2) f64 {
const dx = b.x - a.x;
const dy = b.y - a.y;
return math.sqrt(dx * dx + dy * dy);
}
fn angulo(a: Vec2, b: Vec2) f64 {
return math.atan2(b.y - a.y, b.x - a.x);
}
fn rotacionar(self: Vec2, theta: f64) Vec2 {
const c = math.cos(theta);
const s = math.sin(theta);
return .{
.x = self.x * c - self.y * s,
.y = self.x * s + self.y * c,
};
}
};
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
const a = Vec2{ .x = 3.0, .y = 4.0 };
const b = Vec2{ .x = 7.0, .y = 1.0 };
try stdout.print("Vetor A: ({d:.2}, {d:.2})\n", .{ a.x, a.y });
try stdout.print("Magnitude: {d:.4}\n", .{a.magnitude()});
const norm = a.normalizar();
try stdout.print("Normalizado: ({d:.4}, {d:.4})\n", .{ norm.x, norm.y });
try stdout.print("Mag normalizado: {d:.4}\n", .{norm.magnitude()});
try stdout.print("\nDistância A-B: {d:.4}\n", .{Vec2.distancia(a, b)});
const angulo_graus = Vec2.angulo(a, b) * 180.0 / math.pi;
try stdout.print("Ângulo A->B: {d:.2} graus\n", .{angulo_graus});
// Rotaciona 90 graus
const rotacionado = a.rotacionar(math.pi / 2.0);
try stdout.print("A rotacionado 90°: ({d:.2}, {d:.2})\n", .{
rotacionado.x, rotacionado.y,
});
// Clamp
try stdout.print("\nClamp:\n", .{});
for ([_]f64{ -5.0, 0.0, 3.0, 7.0, 15.0 }) |v| {
try stdout.print(" clamp({d:.0}, 0, 10) = {d:.0}\n", .{
v, math.clamp(v, 0.0, 10.0),
});
}
}
Módulos Relacionados
- std.math Functions — Referência detalhada de funções
- std.crypto — Funções criptográficas
- std.sort — Algoritmos de ordenação
- std.fmt — Formatação de números