人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

(質問訂正)Pythonにおける2進数の扱いが変だと感じるのは私だけでしょうか。


>>> format(31,"06b")
'011111'
>>> format(-31,"06b")
'-11111'
>>> format(32,"06b")
'100000'
>>> format(-32,"06b")
'-100000'

マイナスが2の補数表現でなく単にマイナス符号を付加しただけと言う点は良いとしても、
マイナス時、その数の絶対値を2進数で表したときの最上位ビットが0の場合は最上位ビットが省略されてしまいます。


奇妙だと思いませんか?
なぜこの様な仕様になっているのでしょうか。
Pythonの仕様に詳しい方はご回答お願い致します。



※質問内容が不明確で、かつ誤りがありましたので訂正して再投稿しました。


●質問者: spendarmad
●カテゴリ:コンピュータ
✍キーワード:Python ビット マイナス 仕様 投稿
○ 状態 :終了
└ 回答数 : 7/7件

▽最新の回答へ

[1]たとえばperlでは dev_zer0

下記のPerlソースはコメントの通りの結果になります

#!/usr/bin/perl

printf("%03d\n", 100); # 100

printf("%03d\n", -100); # -100

printf("%03d\n", 10); # 010

printf("%03d\n", 10); # 010

printf("%+03d\n", 100); # +100

printf("%+03d\n", -100); # -100

printf("%03d\n", 10000); # 10000

# Perlには2進数変換がなく10進にしてますけど

そして、Perlのprintfの仕様はCを踏襲しており

http://www.linux.or.jp/JM/html/LDP_man-pages/man3/printf.3.html

printf(3C)では

> もし変換結果がフィールド幅よりも広かった場合、

> フィールドは変換結果が入る幅に広げられる。

と規定されています。

マイナス符号が入ったために変換結果がフィールド指定よりも大きくなり

変換結果が入る幅に広げられたと解釈すれば、私は奇妙とは思いません。

ちなみに、どのような結果が返れば納得するのでしょうか?


[2]Cのprintf qnighy

例えばCのprintfは確か「最小文字数」という意味で桁数の意味は無かったはずです。おそらくformatの文字数指定は等幅フォントにおける表の作成を想定しているものなので桁数より文字数が重視されるのは仕方ないと思います。


[3]>1 うーん spendarmad

>printf("%03d\n", 10); # 010

>printf("%03d\n", 10); # 010

printf("%03d\n", -10);

ならどうなるのでしょう?




>ちなみに、どのような結果が返れば納得するのでしょうか?

2の補数表現は置いておいたとして、

>>> format(-31,"06b")

'-011111'

であれば納得はできます。

なぜなら、

> もし変換結果がフィールド幅よりも広かった場合、

> フィールドは変換結果が入る幅に広げられる。

と解釈するのであれば、6bitという指定を無視し無理やり5bitにしてしまうのではなく、

'-011111'という変換結果が入る幅に広げられるべきだと思うからです。

どうせ6bitの数字の内32以上の物は最上位ビットが1である為-符号が付くと7文字に広げられるのですから、

そこは「妥協して幅を広げようとする」のか、「最上位ビットを削ってでも幅に納める」のか、どちらかに統一されるべきでは?と感じます。




なので

>>> format(-32,"06b")

'-00000'

の様に、いっそオーバーフロー(?)させてしまって「最上位ビットを削ってでも幅に納める」というのでも一応納得できます。


[4]>2 そうでしょうか? spendarmad

>等幅フォントにおける表の作成を想定している

もしそうなのであれば、

format(-32,"06b")

の返り値が7文字なのに、

format(-31,"06b")

の返り値を無理やり6文字に納めようとするのは何故でしょうか。


[5]2進の扱いがおかしいわけではないのです mystashes

formatの役割を勘違いされているのではないでしょうか。

format(-31,'06b') の意味は、数値-31を2進数表記にして”6文字で”表示せよ。です。あくまで文字列操作です。

2進の6bitと解釈せよ、という意味は全く含まれません。bit幅は渡された数値の型依存です。

-31 = "-11111" → 6文字、31 = "011111" → 6文字、与えられた命令通りの結果です。

format(-31,'07b')なら、 それぞれ "-011111", "0011111" です。

ここで厄介なのが、文字数が溢れた場合、表記可能となる最小文字数まで拡張して表示されてしまう点です。

これは仕様なので、しょうがないですね。(私も好みではありませんけど)

正負で桁数を合わせたい場合は、 format(-1,"+06b")としてやって、正のときにも符号を表示させるか、format(-1," 06b")として正のときは空白パディングするしかないと思います。

http://docs.python.org/3.1/library/string.html#formatstrings

formatの仕様が気に入らないという点は私も同意です。

しかし、Pythonの2進数の扱いが変な訳ではありません。

-31からひたすら1ビットシフトしてやれば、真っ当な2進数で扱われていることが判るはずです。(めんどいので-3でもいいですけど)


[6]>4 逆に qnighy

format(-31,"06b")の挙動までが正しくて、format(-32,"06b")の結果は桁あふれだが、文字列を切り捨てるわけにもいかないので伸ばしているだけ、ということだと思います。


[7]>5 理解できました。 spendarmad

>format(-31,'06b') の意味は、数値-31を2進数表記にして”6文字で”表示せよ。です。あくまで文字列操作です。

>2進の6bitと解釈せよ、という意味は全く含まれません。bit幅は渡された数値の型依存です。

なるほど!確かによく考えればそうですよね。

仰られる通りもっと良い仕様に改善できそうではありますが、なぜこの様な出力結果になるのかといった部分は理解できました。

ありがとうございます。

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ