Ziglings 笔记 60: 浮点数的奥秘
浩瀚的数字宇宙
在 Ziglings 的第 60 个练习中,我们离开了精确的整数岛屿,驶向了浩瀚的浮点数海洋。
如果你需要表示原子的大小 ($10^{-10}$) 或者宇宙的直径 ($10^{26}$),整数就无能为力了。这时候我们需要使用 Floating Point (浮点数)。
挑战:航天飞机的重量
我们需要计算航天飞机起飞时的公吨数。 已知:
- 重量:4,480,000 磅。
- 换算:1 磅 = 0.453592 千克。
- 目标:输出整数公吨 (1 公吨 = 1000 千克)。
解决方案
这是使用科学计数法和格式化输出的代码:
const print = @import("std").debug.print;
pub fn main() void {
// 1. 使用科学计数法
// 4480e3 等同于 4480000.0
// Zig 编译器会自动处理 float 字面量之间的乘法
const shuttle_weight: f32 = 0.453592 * 4480e3;
// 2. 格式化输出
// 这里的计算:shuttle_weight (kg) / 1e3 (1000.0) = metric tons
// 格式化 {d:.0}:
// d: 十进制显示
// .0: 精度为 0 (不显示小数部分)
print("Shuttle liftoff weight: {d:.0} metric tons\n", .{shuttle_weight / 1e3});
}
核心知识点总结
1. 浮点字面量
在 Zig 中,任何包含小数点 . 或指数 e 的数字都会被推导为 comptime_float。
4480000是comptime_int。4480e3是comptime_float。 虽然 Zig 允许我们将整数字面量赋值给浮点变量(例如const f: f32 = 100;),但在混合运算时,显式使用浮点格式通常更清晰。
2. 精度控制
格式化字符串 {d:.0} 是处理输出显示的好帮手。
{d:.2}-> 保留两位小数 (3.14){d:.5}-> 保留五位小数 (3.14159) 这只是显示上的舍入,内存中的实际值并没有改变。
3. IEEE-754 细节
练习中的注释展示了 f16 在内存中的二进制结构(符号位、指数位、尾数位)。虽然日常编程不需要手动拼凑这些位,但了解“浮点数是对实数的近似”这一事实至关重要。这意味着 0.1 + 0.2 在计算机中可能并不严格等于 0.3。
后续预告:我们已经学习了基本的数值类型。现在,我们要从单个循环跳出来,进入多重循环的世界。下一篇,我们将学习 Labelled Loops(带标签的循环),看看如何优雅地从嵌套循环中跳出。