web-dev-qa-db-ja.com

異なるタイプの数を乗算/除算/加算/減算する方法は?

Rustハンドブックの第2版を作成していて、古典的な摂氏から華氏へのコンバーターを作成することにしました。

fn c_to_f(c: f32) -> f32 {
    return ( c * ( 9/5 ) ) + 32;
}

これをcargo buildでコンパイルすると、コンパイル時エラーが発生します。

error[E0277]: the trait bound `f32: std::ops::Mul<{integer}>` is not satisfied
 --> src/main.rs:2:12
  |
2 |     return (c * (9 / 5)) + 32;
  |            ^^^^^^^^^^^^^ the trait `std::ops::Mul<{integer}>` is not implemented for `f32`
  |
  = note: no implementation for `f32 * {integer}`

新しいRustプログラマーとして、私の解釈では、float型と整数型を一緒に乗算することはできません。すべての定数を浮動小数点にすることでこれを解決しました。

fn c_to_f(c: f32) -> f32 {
    return ( c * ( 9.0/5.0 ) ) + 32.0;
}

これは私に予約を残します。 C/C++/Java/Pythonから来て、異なるタイプの数に対して単純に算術を実行できないことを知って驚いた。私がここで行ったように、単にそれらを同じタイプに変換するのは正しいことですか?

15
Kenny Worden

TL; DRasは、プリミティブ数値タイプ間で変換する最も一般的な方法ですが、それを使用するには考える必要があります。

_fn c_to_f(c: f32) -> f32 {
    (c * (9 as f32 / 5 as f32)) + 32 as f32
}
_

ただし、この例では、浮動小数点リテラルを使用して開始する方が合理的です。

_fn c_to_f(c: f32) -> f32 {
    (c * (9. / 5.)) + 32.
}
_

realの問題は、混合型の演算を行うのが少し複雑なことです。

掛けるなら1T by Tの場合、通常、少なくとも基本型では、型Tの結果が得られると予想されます。

ただし、タイプを混合する場合、いくつかの問題があります。

  • 符号の混合、
  • 混合精度。

それで、例えば、_i8 * u32_の理想的な結果は何ですか?すべての_i8_および_u32_値の完全なセットを包含することができる最小のタイプは_i64_です。それが結果であるべきですか?

別の例として、_f32 * i32_の理想的な結果は何ですか?すべての_f32_および_i32_値の完全なセットを包含することができる最小のタイプは_f64_です。それが結果であるべきですか?

そのような拡大を行うという考えはかなり混乱します。また、パフォーマンスにも影響します(_f32_での操作は、ベクトル化されると、_f64_での操作よりもはるかに高速になる可能性があります)。

これらの問題のため、今のところRustは明示的である必要があります:どのタイプで計算を実行しますか?どのタイプが特定の状況に適していますか?

次に、asを使用して適切にキャストし、どの丸めモードを適用するかを検討します(.round().ceil().floor()、または.trunc()浮動小数点から積分に移行する場合)。

1加算、減算、除算は同様の方法で機能します

17
Matthieu M.