10進数をn進数に変換する② 負数と小数

前回、10進数からn進数、n進数から10進数へ戻す方法を記載しました。
では、負数や小数はどのように変換するのでしょうか?

目次

  1. 負数の変換
  2. 小数の変換
  3. プログラミングをするとどうなるのか
  4. まとめ

負数の変換

負数の場合、普通はマイナス(-)をつけて表現すればよいのですが、Javaをはじめプログラム言語の多くでは上位1ビットを正負の符号として利用しています。
つまりshort型を例に取ると「1000 0001」はマイナス1(-1)間違いです-127ということになります。
(2018/10/31)修正
ということは型の説明でもしましたがshort型は32767すなわち「0111 1111」が最大値となるわけです。
次のコードを実行してください。

結果はどうなったでしょうか?
2147483648となりましたか?おそらく、こうなっているはずです。

-2147483648となっていますね、なぜでしょう?
これは「桁あふれ」という状態で、先ほど説明したように±符号を上位1ビットに判断させているからなる現象です。
基本的にどの言語でも起こり得ます。
どういうことかというと、2147483647は2進数変換すると「0111 1111 1111 1111 1111 1111 1111 1111」です。さて、この内符号を担当しているのは上位1bitの「0」の部分になります。つまり、ここに「1」を加算すると「1000 0000 0000 0000 0000 0000 0000 0000」になり、上位1bitが1に反転し、マイナスになってしまうのです。「1000 0000 0000 0000 0000 0000 0000 0000」は-2147483648を表すので、結果が大幅に変わってしまうのです。
これはプログラミングをする上での特性ですので、気をつけて使う必要があります。

小数の変換

さて、小数の場合はどうするのかというと
例えば「0.625」を2進数にしましょう。どうするのかというと、小数点部分を2倍していきます。

この切り捨てた部分が少数となり「0.101」が「0.625」を2進に変換した値となります。
16進法の場合は同様に、変換したい小数を16倍して小数部だけを16倍し続ければよいわけです。

プログラミングをするとどうなるのか

次のコードを入力してください

さて、結果はどうなっているでしょうか?「0.6」と表示されましたか?
このような結果になっていると思います。

0.6000000000000001なんで?と思う方もいるかもしれません。
実はこれで間違いではないのです。どこでおかしくなっているのか確認していきましょう。
まずは、10進法の0.1を2進法の小数に変換しましょう。

これを見て途中で気づいた方もいるかもしれませんが、5回目から小数の部分が同じ値になっています。最終的にはずっと繰り返していくことになります。
0.2、0.3も同様にいつまでも計算が終わらない状態になります。これを「循環小数」と呼びます。
10進法だと1/3=0.333333333…とかがあたりますね。
これは、変換をする時に必ず起きる現象なので、言語を問いません。Javaの場合は「BigDecimal」というクラスを使います。

これで計算結果は「0.6」になったかと思います。
細かいことはもっとJavaを知ってからのほうが良いと思いますが、簡単に言うと割り切れない数を丸めて(四捨五入)して、近似値で計算をさせているようなものです。
詳しくは二進化十進数 (BCD、Binary-coded decimal ) について書いてあることを「BigDecimal」がやってくれると思ってくれれば構いません。
こういったクラスを利用して便利にコードを組むことができるのもJavaの利点の一つですね。

まとめ

  • 負数を扱うときには気をつける。
  • プログラミングの場合、負数は上位1ビットを使って±変換をしているので、大きな数字を扱うときには注意が必要です。

  • 不用意にfloatやdouble型を使わない
  • 実際、Bigdecimalも初学者の方には使いにくいと思うので、だんだん慣れていけばいいと思います。

 

このサイトをフォローする!

10進数をn進数に変換する② 負数と小数” に対して1件のコメントがあります。

  1. FMT店長 より:

    2018/10/31:記事の間違いを修正しました。
    負数の値の間違いの修正です。

この投稿はコメントできません。