TAKOYAKING’s blog 一覧

TAKOYAKING’s blog

たこ焼き系

Rust: i8のキャストと2の補数

型キャスティング | Rust by Example
このサイトで型キャスティングを学びました。
その時 2の補数で型のキャスティングが行われると符号が反転する場合があることを知りましたので、まとめてみます。

現象

// 符号付きの型にキャストする場合、結果は以下の2つを行った場合に等しい
// 1. 対応する符号なしの型にキャストする。
// 2. 2の補数(two's complement)をとる

// 128をu8にキャストすると128となる。128の8ビットにおける補数は -128
println!(" 128 as a i8 is : {}", 128 as i8);

128をi8でキャストすると-128になります。
これはRustが符号付きでは以下のルールでキャストするためです。

符号付きの型にキャストする場合、結果は以下の2つを行った場合に等しい
1. 対応する符号なしの型にキャストする。
2. 2の補数(two's complement)をとる

補数とは

「2の補数」「1の補数」について覚書 - Qiita
このサイトがわかりやすかったです。

  • 足すと桁上がりする数のうち最小の数。 (10進数なら98の補数は2)
  • 足しても桁上がりしない数のうち最大の数。 (10進数なら98の補数は1)

特に2進数は

  • 2の補数(足すと桁上がりする数のうち最小の数。) (ビット反転)
  • 1の補数(足しても桁上がりしない数のうち最大の数。) (ビット反転した数に1を足す)

があります。

128をi8でキャストすると-128になる理由

キャスト (型変換) | サイト構築日記
Rustではないですが、他の言語でも同様の現象があるので、こちらのサイトがわかりやすかったです。

-128になるのをみて、一瞬思ったのが、「128の2の補数は128ではないか」と思いました。
128の2の補数は128で間違い無いのですが、解説を読むとわかりました。

i8の範囲は「-128~127」なので8個のbitを使用しますが、8bit目は符号の役割を果たします。
なので128はi8の範囲からあふれています。
128は2進数では「10000000」となりますが、i8では8個目のビットが立っているとマイナス表現負の数は2の補数で処理されるので-128と表現されてしまいます。
これが、128の2の補数は128ですがi8は-128となってしまう原因です。

感想

補数という言葉を知らなかったので、知れてよかったと思いました。rustだけではなく、他の言語でも同様の現象起こりそうなので、ハマった時に思い出せたら役に立つと思いました。