アカウント名:
パスワード:
212名無し募集中。。。2007/04/14(土) 19:10:46.28 0>>210ある物流系システムの開発現場で…SE:○○君 ここの値が実際の値の2倍の数値が表示されてるんだけど…○○:わかりました。修正します。
…と言って彼はprintfするときその値を2で割ったという
桁溢れしたら、どうするのだろう。
負数だとまずいことになる。
-1を右シフトするとどうなりますか。
># ちなみにいまどきのコンパイラだったら、(整数を)定数2で割るのもシフト命令に展開してくれますよね。
なりません。
負の数の除算と右シフトは結果が異なるので、整数(int)除算は単なるシフト命令ではなく、シフト命令と補正コードに展開されます。シフト命令に展開されるのは正の整数(unsigned int)の除算の場合のみです。
/* シフトと補正になる */int foo(int a) { return a/2;}/*_foo: movl 4(%esp), %eax movl %eax, %edx shrl $31, %edx addl %edx, %eax sarl %eax ret*/
/* シフトになる */unsigned int bar(unsigned int a) { return a/2;}
/*_bar: movl 4(%esp), %eax shrl %eax ret*/
> ># ちなみにいまどきのコンパイラだったら、(整数を)定数2で割るのもシフト命令に展開してくれますよね。> なりません。
いえ、なるかならないかは処理系依存です。C99に限定するならば「なりません」と言えますが。
それは「いまどき」の定義に依りますが、組み込みまで含めて、実用的に使われているすべてのCコンパイラがC99だと断言するにはまだ早いでしょう。(あと何年で実用的なレベルで置き換わるかは私には予測もできません)
その上、もとのコードがCかC++かのどちらを意図していたかは私は知りませんが、C++では依然、実装依存です。
VB だったんですよ、きっと。シフト演算がサポートされていないことに絶望しつつ、乗除算で逃げたのは何を隠そう私です。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
物事のやり方は一つではない -- Perlな人
2倍 (スコア:5, おもしろおかしい)
212名無し募集中。。。2007/04/14(土) 19:10:46.28 0
>>210
ある物流系システムの開発現場で…
SE:○○君 ここの値が実際の値の2倍の数値が表示されてるんだけど…
○○:わかりました。修正します。
…と言って彼はprintfするときその値を2で割ったという
Re:2倍 (スコア:3, おもしろおかしい)
Re:2倍 (スコア:1)
# 論理右シフト だと別の問題を呼ぶかも...
Re:2倍 (スコア:1)
Copyright (c) 2001-2014 Parsley, All rights reserved.
素朴な疑問 Re:2倍 (スコア:1)
桁溢れしたら、どうするのだろう。
Re: (スコア:0)
負数だとまずいことになる。
Re: (スコア:0)
どして?
printf関数とシフト演算子があって、符号つき/符号なしを区別しないでシフトを行う
処理系ってあるのでしょうか。
Re:2倍 (スコア:1, すばらしい洞察)
-1を右シフトするとどうなりますか。
Re: (スコア:0)
-1は符号付だから右シフトは算術右シフト。
-1はいくら算術右シフトをしても-1
-2なら-1。
元ネタより、数は偶数であるので-1は存在せず、もし有ったとしても
切捨て,切り上げの誤差範囲であるので、期待通りとみなせると推測。
どこかまずいですか?
Re: (スコア:0)
Oh!処理系依存なんだ。
でも実際に、符号付を'>>'で論理シフトするのは存在するの?
汎用CPUで算術シフトを持たないCPUを想像できず、またはそれを利用しないで
一律論理シフトにしてしまうコンパイラも同様に想像できず。なんで処理系依存なのかしらん。
数値演算しないプロセッサも想定して?でも四則演算は必須演算子ですよね?
これも"仕様のバグ"か?
# ちなみにいまどきのコンパイラだったら、(整数を)定数2で割るのもシフト命令に展開してくれますよね。
# 「2のべき乗の乗除算はシフトにしよう」なんて、定数なら既にコンパイラがやってくれているとおもいます。
Re:2倍 (スコア:1)
># ちなみにいまどきのコンパイラだったら、(整数を)定数2で割るのもシフト命令に展開してくれますよね。
なりません。
負の数の除算と右シフトは結果が異なるので、整数(int)除算は単なるシフト命令ではなく、シフト命令と補正コードに展開されます。
シフト命令に展開されるのは正の整数(unsigned int)の除算の場合のみです。
/* シフトと補正になる */
int foo(int a) {
return a/2;
}
/*
_foo:
movl 4(%esp), %eax
movl %eax, %edx
shrl $31, %edx
addl %edx, %eax
sarl %eax
ret
*/
/* シフトになる */
unsigned int bar(unsigned int a) {
return a/2;
}
/*
_bar:
movl 4(%esp), %eax
shrl %eax
ret
*/
Re:2倍 (スコア:1)
> ># ちなみにいまどきのコンパイラだったら、(整数を)定数2で割るのもシフト命令に展開してくれますよね。
> なりません。
いえ、なるかならないかは処理系依存です。
C99に限定するならば「なりません」と言えますが。
Re: (スコア:0)
Re:2倍 (スコア:1)
それは「いまどき」の定義に依りますが、
組み込みまで含めて、実用的に使われている
すべてのCコンパイラがC99だと断言するにはまだ早いでしょう。
(あと何年で実用的なレベルで置き換わるかは私には予測もできません)
その上、もとのコードがCかC++かのどちらを意図していたかは私は知りませんが、
C++では依然、実装依存です。
Re: (スコア:0)
VB だったんですよ、きっと。
シフト演算がサポートされていないことに絶望しつつ、乗除算で逃げたのは何を隠そう私です。
VB6以前のはなしなら (スコア:0)
&あたりで計算させれば問題なくシフト演算できます