unsigned型の引き算について危ないということは知りつつよく理解していなかったので調査。
コード
# include <string>
# include <iostream>
# include <chrono>
# include <cstdint>
# include <cmath>
using namespace std;
void checkDiff(uint32_t l, uint32_t r, bool isLeftBigger)
{
int a = l - r;
int b = r - l;
if (a < b && isLeftBigger)
{
cout << a << " is smaller than " << b << endl;
}
else if (a > b && !isLeftBigger)
{
cout << a << " is larger than " << b << endl;
}
else
{
cout << "OK" << endl;
}
}
int main(int argv, char* argc[])
{
checkDiff(UINT_MAX, UINT_MAX - 1, true);
checkDiff(UINT_MAX - 1, UINT_MAX, false);
checkDiff(UINT_MAX, 0, true);
checkDiff(UINT_MAX, 1, true);
checkDiff(0x7FFFFFFFU, 0xFFFFFFFFU, false);
return 0;
}
結果
OK
OK
-1 is smaller than 1
-2 is smaller than 2
OK
続行するには何かキーを押してください . . .
考察
引く側と引かれる側をひっくり返したら符号が逆になるだけ。よく考えてみたらそりゃそうだ。
減算の結果が0x80000000以上になる場合にintで受けてたりしたらバグるし、素直にどちらが大きいか判定してから引き算しよう。