Zig之数值运算与操作

0 阅读4分钟

Zig 追求的是显式性(Explicitness)和对硬件行为的精确控制。

类型

整数

Zig 支持任意位宽的整数。通过在 u(无符号)或 i(有符号)后加上数字即可定义,例如 i7 代表有符号的 7 位整数。整数类型允许的最大位宽为 65535

  • 硬件对齐:当需要操作非标准硬件(如网络协议中的 3-bit 标志位或特定的 FPGA 寄存器)时,能极大减少位掩码(bit-masking)的痛苦。
  • 类型安全:编译器会确保不会意外地将一个 u4 的值存入期待 u3 的变量中。

usizeisize 的大小取决于目标 CPU 架构:32 位系统上是 32 位,64 位系统上则是 64 位。

const u3 = u3;          // 3位无符号整数 (0-7)
const i12 = i12;        // 12位有符号整数
const u128 = u128;      // 128位

浮点数

浮点数类型包括 f16f32f64f80f128,以及 c_longdouble(对应 C ABI 的 long double)。

comptime_float 具有 f128 的精度和运算能力。

浮点字面量可以隐式转换为任意浮点类型。如果浮点字面量没有小数部分,它还可以隐式转换为任意整数类型。

Zig 在浮点数处理上非常谨慎,默认遵循 IEEE 754 标准(strict模式),但在特定作用域内允许性能优化。

  • 显式浮点模式:默认情况(strict模式)下,编译器不允许进行可能改变精度的重排(如将 (a + b) + c优化为 a + (b + c))。@setFloatMode(.optimized)下允许编译器为了性能进行激进优化,相当于 GCC 的 -ffast-math 标志。
  • 编译时常量表达式 (comptime):Zig 的 comptime 允许在编译期以无限精度进行数值计算,只有在最终赋值给运行时变量时,才会根据目标类型进行截断或舍入。

操作

显示转换

Zig 禁止任何可能导致精度损失的隐式转换。

  • 隐式类型提升 (Type Promotion):仅当转换是安全且无损时(例如 u8u16),才允许隐式发生。

除法运算符 / 处理整数时,如果除数为 0 且在安全模式下,会直接触发 Panic。 对于浮点数,它遵循 IEEE 754,产生 infNaN

类型强制转换

内置函数说明
@as(T, value)安全类型标注。将 value强制转为类型 T。如果转换会损失信息或破坏类型规则,则编译报错;适用于向上转型(如 u8 -> u16
@intCast(T, value)整数类型强制转换。在整数类型间转换,不检查值的合理性。在安全构建模式下,如果 value 超出 T 的范围会 panic;在 ReleaseFast 下会静默截断。
@floatCast(T, value)浮点数类型强制转换。在不同浮点类型(如 f64 -> f32)间转换,可能损失精度。
@truncate(T, value)截断。将整数 value 的高位截断,以匹配目标类型 T 的位宽。
@bitCast(T, value)按位重解释。将一个值的底层二进制表示不修改任何位地解释为另一个类型。要求源类型和目标类型的大小相同。
@floatFromInt(value)将整数安全地转换为浮点数。
@intFromFloat(value)将浮点数转换为整数。如果浮点值超出目标整数范围,则为可检测的非法行为。

溢出相关函数

这些函数返回一个元组,包含是否溢出的布尔标志和运算结果

内置函数说明
@addWithOverflow(a, b)返回 struct { overflow: u1, result: T }
@subWithOverflow(a, b)返回 struct { overflow: u1, result: T }
@mulWithOverflow(a, b)返回 struct { overflow: u1, result: T }
@shlWithOverflow(a, b)返回 struct { overflow: u1, result: T }

在需要明确环绕或饱和行为时避免安全检查,Zig 提供了特殊的运算符变体

运算符说明行为描述
+%, -%, *%环绕算术保证以二进制补码环绕(Wrap-around) 的方式处理溢出,即结果被截断到类型宽度。例如,@as(u8, 255) +% 1 的结果是 0
+|, -|, *|饱和算术保证以饱和(Saturating) 方式处理溢出,即结果会“粘”在目标类型的最大值或最小值上。例如,@as(u8, 250) +| 10 的结果是 255

std.math

std.math 库提供了更丰富的数学功能,是对内置函数的补充。

  • 数学常量:如 std.math.pi, std.math.e, std.math.tau, std.math.ln2 等。
  • 数值比较:approxEqAbsapproxEqRel 用于浮点数的近似相等比较。
  • 工具函数:如 clamp(钳制), min/max(最小/最大值), gcd(最大公约数)。
  • 特殊值判断:isFinite(是否为有限值), isNaN(是否为非数值)。
  • 更复杂的数学函数:如三角函数、双曲函数、指数/对数函数等。