
本文解析 rust 的 `..` 半开区间(左闭右开)与 go/ruby 中常见闭区间逻辑的差异,指出因边界处理不一致导致求和结果不同的根本原因,并提供跨语言对齐的正确写法。
Rust 的范围表达式(如 0..n)默认为左闭右开区间,即包含起始值 0,但不包含结束值 n。因此,0is..100000000is 实际遍历的是整数 0, 1, 2, ..., 99999999 —— 共 100,000,000 个数,最大值为 99999999。
而你在 Go 和 Ruby 示例中使用的逻辑实质上是 1..99999999(Go 的 i 跳过了 99999999,实际求和范围是 1 到 99999998(含),共 99,999,998 个数,自然得到更小的结果 4999999850000001。
要使三门语言计算完全相同的数学和(即 0 + 1 + 2 + ... + 99999999 = 4999999950000000),需统一范围语义:
✅ 正确对齐写法(全部计算 0..100000000 或 0 ≤ i ≤ 99999999):
-
Rust(当前已正确):
fn main() { let mut sum = 0i64; // 使用 i64 避免溢出(0..100_000_000 的和 ≈ 5e15) for i in 0..100_000_000 { sum += i; } println!("{}", sum); // 输出:4999999950000000 } -
Go(修正为包含 99999999):
package main import "fmt" func main() { var sum int64 = 0 for i := int64(0); i < 100000000; i++ { // 或 i <= 99999999 sum += i } fmt.Println(sum) // 输出:4999999950000000 } -
Ruby(修正为包含 99999999):
sum = 0 (0...100_000_000).each { |i| sum += i } puts sum # 输出:4999999950000000
⚠️ 注意事项:
- Rust 中旧语法 0is 已废弃(is 不是合法类型后缀),应使用 i32、i64 等显式类型,且此处必须用 i64(i32 最大值仅约 21 亿,远小于求和结果);
- Go 默认 int 在 64 位系统可能为 int64,但为可移植性,建议显式声明 int64;
- Ruby 的 Bignum 自动处理大整数,无需手动指定类型,但范围写法 ...(右开)与 ..(右闭)需严格区分。
总结:差异并非“数学错误”,而是语言设计对区间语义的约定不同。Rust 坚持半开区间的工程惯例(与数组索引、切片保持一致),而 Go/Ruby 示例误用了不匹配的边界条件。统一范围定义后,三者结果完全一致 —— 这正是理解底层语义比盲目对照输出更重要的原因。










