为什么在将整数加到浮点数时会出现错误?

33

我开始学习 Rust,尝试了这个程序:

fn main() {
     let a = 5;
     let b = 5.5;
     let k = a + b;
     println!("{}", k);
}

并且它显示了这个错误:

error[E0277]: cannot add a float to an integer
 --> src/main.rs:4:16
  |
4 |      let k = a + b;
  |                ^ no implementation for `{integer} + {float}`
  |
  = help: the trait `std::ops::Add<{float}>` is not implemented for `{integer}`

代码有错误吗?


2
欢迎来到StackOverflow!在SO上,我们期望您展示自己解决问题的努力。请参考此指南获取有关如何在SO上提问的更多信息。 - Lukas Kalbertodt
7
@Enzokie 的说法不完全正确。CodeReview 仅适用于可运行的代码。由于这段代码无法正常工作,在理论上问题更适合在 SO 上讨论。 - Lukas Kalbertodt
好的,我明白了,那似乎很合理。 - Enzokie
1
请花一点时间查看一下我们对您的问题所做的一些编辑。最重要的是,您的问题应该有一个好的标题(我知道这很难想出来!)。 - Shepmaster
1
@JøêGrèéñ 因为你不能这样做。Rust不允许你将整数加到浮点数上。 - Veedrac
显示剩余2条评论
1个回答

64

从技术上讲,答案是:因为没有人编写 impl Add<f64> for i32 {}

有点调皮的答案是:因为Rust不希望你自己给自己惹麻烦。

更长、可能更有用的答案是...

在计算机中,整数和浮点数都有一个有限的范围,最终由我们用来表示它们的位数驱动。在Rust中,除非另有约束,否则整数的默认类型是i32,浮点数的默认类型是f64

整数类型不允许您有小数部分,而浮点类型只能准确表示有限数量的整数。如果Rust允许您添加这两种类型,那么它将为您做出关于哪个数据片段更不重要的决定,这并不是您希望系统编程语言做的事情!

以下是我能看到的选项:

  1. 引发错误,强制程序员选择他们需要的数据类型。
  2. 自动将两个数字转换为整数,丢弃任何潜在的小数值。
  3. 自动将两个数字转换为浮点数,不正确地表示更大的整数值。

在这些选择中,只有错误是合理的。

还有可能引入一种可以精确处理任意精度的类型。不幸的是,这些类型对于处理器来说不再是“便宜”的,因此您必须在性能和精度之间做出权衡。

如果程序员希望执行某些转换,则可以使用asFrom来强制转换值:

f64::from(a) + b;
a + b as i32 

另见:


Veedrac添加

[此答案给出了]“0u32 + 0u64应该起作用”的印象,但是Rust不会进行任何数值提升,即使提升是无损的。此外,i32f64是一种无损提升,因为f64有52位尾数。

虽然这些类型的宽化提升确实是无损的,但它们涉及隐式增加您的内存要求。例如,以前只需要32位,现在需要64位。除了内存要求之外,还有语义上的考虑。如果一个值应该只需要一个u8(0-255),那么将其增加可能超出该范围就没有意义。知道是否适合进行这样的转换完全取决于程序员。

使用From可以确保您只使用无损的数字转换。


5
虽然这个解释很好,但我认为它是误导性的。它给人的印象是 0u32 + 0u64 应该可以工作,但是 Rust 不会进行任何数值提升,即使提升是不会有损失的。此外,i32f64 是一种无损提升,因为 f64 有一个52位的尾数。 - Veedrac
1
但是为什么呢?C语言让我使用32位整数与64位浮点数。 - Jøê Grèéñ
2
Rust通常不支持隐式转换。这就是事实,但我真的更喜欢这种方式。 - E net4
12
@JøêGrèéñ,我不确定还能补充什么,我已经给出了多个原因,解释为什么Rust不进行这些隐式转换。C语言允许一些Rust不允许的操作,例如对空指针进行解引用,但这并不意味着这是一个应该被延续的好主意。我想你的问题也可以反过来问:为什么C语言允许将 double 加到 int32_t - Shepmaster
1
@zombiesauce 这与促销无关。Rust不会警告您有关f64 + f64的信息,这种操作具有更多的损失操作和更大的幅度。 - Veedrac
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接