如何在Rust中添加或乘以两个i16以形成一个i32而不会溢出?

Pet*_*ron 3 integer-overflow rust

如何i16在Rust 中将两个数字相加或相乘成一个更大的数i32而不会溢出?

let a: i16 = i16::max_value();
let b: i16 = i16::max_value();
let c: i32 = a + b; // throws EO308 "Expected `u32`, found `u16`
Run Code Online (Sandbox Code Playgroud)

rod*_*igo 7

Rust中没有积分提升或隐式强制转换,因此您必须手动进行所有类型转换。

对于演员表,可以使用<value> as <type>。但是,如果目标类型是原始类型的超集,并且将其转换为不会丢失信息(例如您的案例),则可以使用<type>::from以下方法自我记录:

let a: i16 = i16::max_value();
let b: i16 = i16::max_value();
let c: i32 = i32::from(a) + i32::from(b);
assert_eq!(c, 65534);
Run Code Online (Sandbox Code Playgroud)

这种特殊情况不会溢出,但是对于其他情况,您可以使用{integer}::checked_*()函数防止溢出:

let a: i16 = i16::max_value();
let b: i16 = i16::max_value();
let c: Option<i16> = a.checked_add(b);
assert_eq!(c, None); //overflow!
Run Code Online (Sandbox Code Playgroud)

请注意,在调试版本中,默认情况下会溢出整数运算恐慌。

如果您要包装算术,就像在旧的C语言中一样,您可以使用{integer}::wraping_*(),它可以用于有符号和无符号值。

let a: i16 = i16::max_value();
let b: i16 = i16::max_value();
let c: i16 = a.wrapping_add(b);
assert_eq!(c, -2);
Run Code Online (Sandbox Code Playgroud)

  • 请注意,典型的整数加法运算中的溢出仅在调试模式下编译时会发生混乱。 (2认同)
  • @E_net4:不完全是。Rust *语言* 指定溢出的结果是未指定的,并且可能是恐慌。`rustc` *编译器*允许使用开关选择两种行为之一:恐慌或包装;此外,它还“默认”在调试中恐慌并在发布中包装,但用户始终可以更改此设置。理想情况下,“rustc”默认会“总是”出现恐慌,但是 LLVM 对此类代码的优化很差,而且恐慌的存在通常会阻碍矢量化,因此 Release 的默认值必须进行包装以匹配“目前”的 C 性能。 (2认同)

Ser*_*sev 1

您可以将它们都投射到i32添加之前。

let c: i32 = (a as i32) + (b as i32); 
Run Code Online (Sandbox Code Playgroud)

  • @SergioTulentsev:“as”工作正常,只是不便于维护。如果“a”的类型切换到“i64”,则“a as i32”操作将继续编译,现在会默默地截断该值。`From` 仅为转换而定义,转换不会失败,因此会停止编译。`TryFrom` 是为所有转换定义的,但返回一个必须在运行时解包的 `Option&lt;Target&gt;`;它通常用于*可能*失败的转换。 (2认同)