インデックスを前方または後方に移動するリストのサイクルメソッドを記述しています。次のコードを使用して逆方向に循環します。
(i-1)%list_length
この場合、i
はusize
型であり、符号なしであることを意味します。 i
が0に等しい場合、「オーバーフローを伴う減算」エラーが発生します。この問題を回避するために正しいキャスト方法を使用しようとしました。
((i as isize)-1)%(list_length as isize)) as usize
これにより、整数オーバーフローが発生します。
私はエラーが発生する理由を理解しています。現時点では、インデックスが0に等しいかどうかを確認することで問題を解決しましたが、変数を正しい型にキャストすることで解決する方法があるかどうか疑問に思っていました。
DK。指摘 のように、整数レベルでのセマンティクスのラップは望ましくありません。
fn main() {
let idx: usize = 0;
let len = 10;
let next_idx = idx.wrapping_sub(1) % len;
println!("{}", next_idx) // Prints 5!!!
}
代わりに、モジュロロジックを使用してラップアラウンドします。
let next_idx = (idx + len - 1) % len;
これは、len
+ idx
が型の最大値よりも小さい場合にのみ機能します。これは、u8
の代わりにusize
; idx
を200に、len
を250に設定するだけです。
2つの値の合計が常に最大値よりも小さくなることを保証できない場合は、おそらく「チェック済み」の操作ファミリを使用します。これは、既に述べたのと同じレベルの条件チェックを行いますが、きちんと1行に結び付けられています。
let next_idx = idx.checked_sub(1).unwrap_or(len - 1);
コードでオーバーフロー操作が発生する可能性がある場合は、 Wrapping
を使用することをお勧めします。許可すると、キャストやオーバーフローのパニックを心配する必要はありません。
use std::num::Wrapping;
let zero = Wrapping(0u32);
let one = Wrapping(1u32);
assert_eq!(std::u32::MAX, (zero - one).0);