Rustのrotate shift
超小ネタ。Rustには標準でrotate shiftが用意されている。例えば左に1つずらすrotate_leftだと、調べてみると基本的な型にはそれぞれ実装されている。ちなみに専用のtraitがあるというわけではないらしい。
挙動に関しては特に驚くようなことはない。もちろん、これとは別に<<
演算子が用意されていて、挙動が異なるとアナウンスされている。
Please note this isn't the same operation as the << shifting operator!
let o = 0b11110000u8; assert_eq!(o.rotate_left(3), 0b10000111); assert_eq!(o << 3, 0b10000000);
ここまではいいのだが、試しにsignedな数値に同じことをしようとしたら、怒られた。
fn test_rotate_shift() { let p = 0b10000000i8; assert_eq!(p.rotate_right(1), 0b01000000); assert_eq!(p >> 1, 0b11000000); }
error: literal out of range for i8 --> src/main.rs:158:13 | 158 | let p = 0b11110000i8; | ^^^^^^^^^^^^ help: consider using `u8` instead: `0b11110000u8` | = note: `#[deny(overflowing_literals)]` on by default = note: the literal `0b11110000i8` (decimal `240`) does not fit into the type `i8` and will become `-16i8`
どうやら、overflowing_literals属性というのをつけないといけないらしい。
#[allow(overflowing_literals)] fn test_rotate_shift() { let p = 0b10000000i8; assert_eq!(p.rotate_right(1), 0b01000000); assert_eq!(p >> 1, 0b11000000); }
これで無事に、signedな数値を、マイナスの符号がついていても2進リテラル表記できるようになった(符号がプラスならば属性がなくとも表記可能)。当然の話だが、rotateの結果は符号を保存しないがshift演算子は符号を保存することにご注意。