signed int と unsigned int の掛け算。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Ma

signed int と unsigned int の掛け算。

#1

投稿記事 by Ma » 15年前

(タイトル変えました。下記は原因が分かっていなかったころの投稿です。)


おせわになってます。
C++、Visual C++ 2008 Express Edition, windows 7 64 bit
の環境でプログラミングしていたところ
ブレイクポイントを設けることで、以下の二通りの計算で違う結果が出ていることが分かりました。

その1
height = editMessages.size()*15*(mouseCord[1]-gosa)/600;

その2
height = editMessages.size()*15/600*(mouseCord[1]-gosa);

私は、両方とも同じ結果になる。そう思っていました。


mouseCord は
int mouseCord[2];
として宣言。値は、38

gosa は
static int gosa;
として宣言。値は40。

height は
int height;
として宣言。値は、90だった。

editMessages

deque<string> editMessages;
として宣言。(std::deque)  editMessages.size()の値は、493。unsigned int ですね。

となっておりました。

結果は、
その1の方法では
heightの値が7158254になってしまいました。

493*15*(38-40)/600
これで-24.64とかになると思っていたのですが・・・。


その2の方法では、思ったとおりの
493*15/600*(38-40) = -24.64
つまりheightは -24になりました。

何か、私は勘違いしていますか?
四則演算からなにか勘違いしているのでしょうか。。。。
それとも何か型(static unsigned signed とか)の組み合わせ?? 画像

Ma

Re:四則演算結果が異なる?

#2

投稿記事 by Ma » 15年前

追記
height = (mouseCord[1]-gosa)*(signed int)editMessages.size()*15/600;
↑OK
height = (mouseCord[1]-gosa)*editMessages.size()*15/600;
↑ダメ

ということで、 unsigned int と signed int をかけた事が原因なのはわかりました。
でも、これで解決にしちゃうとちょっとすっきりしないので、
よろしければこの現象の説明を、お願いします。

具体的には、
どうビット単位の計算の違いがあるのか、
私が思ったとおりに動くかどうかは環境依存なのか

という点を教えてもらえると助かります。 画像

御津凪

Re:signed int と unsigned int の掛け算。

#3

投稿記事 by 御津凪 » 15年前

この場合、掛け算をする時は signed 、 unsigned 関連無く正しい計算をしています。
しかし、割り算をする時、 signed 、 unsigned では計算結果が変わっています。

まず、
(mouseCord[1]-gosa)
は int型 ですが、
editMessages.size() が unsigned int型 のため、 unsigned int 型 同士として掛けてしまうので、
以降 unsigned int 型として計算されています。

次に、

(mouseCord[1]-gosa)*editMessages.size()*15
        ↓
(38 - 40) * 493 * 15

の時点で、値は signed では -14790 、 unsigned では 4294952506 で、
16 進数では共に 0xFFFFC63A です。(つまりこの時点までは双方向のキャストをしても結果は同じ)

この signed 、 unsigned の値を 600 で割ると、値は signed では -24 、 unsigned では 7158254 となり、
割り算をする時点で結果が変わることが分かります。

Ma

Re:signed int と unsigned int の掛け算。

#4

投稿記事 by Ma » 15年前

おおお、納得できました!
最初は分からないと思いましたけれども、なんどか読んだら理解できました。


つまり

int nantoka = (signed int のなにか)*(unsigned int の何か)
とした場合、16進数では一致しているので最後にint に自動?キャストされるから、問題なしと。
つまり
int nantoka = (int)((signed int のなにか)*(unsigned int の何か))
であると。

それにたいして、
int nantoka = (signed int のなにか)*(unsigned int の何か)/600
とすると/600までがunsigned int になり、それを600で割ることで unsigned int の値として割ったことになり、それが最後にint にキャスト。
ということですね。

では

int nantoka = (signed int)((signed int のなにか)*(unsigned int の何か))/600

としても意図通りに正しくできるわけですね。

ありがとうございました。
間違ってたらおしてください(汗

閉鎖

“C言語何でも質問掲示板” へ戻る