整数の除算 @ C++
a/b
とか a%b
の挙動についてメモ.
a
, b
の一方が負である場合は処理系依存(C/C++のバージョンにもよる?)で,
多くの処理系で「実数の割り算の値a/bを0方向に丸める」ということらしい.
ただし (a/b)*b + a%b == a
は成り立つようになっている.
先日書いた 関数オブジェクト @ C++ - buq’s blog について考えていて気になったので.(こちらのコードも修正した)
参考 : - Integer division rounding with negatives in C++ - Stack Overflow - BohYoh.com-C/C++ FAQ 負数に対する除算の結果がおかしいのはどうしてですか。
以下実験コード
#include <iostream> #include <iomanip> #include <vector> #include <numeric> #include <algorithm> #define range(container) container.begin(), container.end() #define say(smth) std::cout << smth << std::endl using namespace std; typedef int (*func_type) (int, int); int mymod(int a, int b){ return a%b; } int mydiv(int a, int b){ return a/b; } // func. name div occupied by C language int mynum(int a, int b){ return (a/b) * b + a%b; } // returns numerator void show_func_result_table(const vector<int> as, const vector<int> bs, func_type f){ cout << "b\\a|"; for(auto && a : as) cout << setw(3) << a; cout << endl; cout << "===="; for(auto && a : as) cout << "==="; cout << endl; for(auto && b : bs){ //if(b == 0) continue; cout << setw(3) << b << "|"; for(auto && a : as) cout << setw(3) << f(a,b); cout << endl; } } int main(){ const int n = 10; vector<int> a(n), b(n); //iota(a.begin(), a.end(), -4); iota(range(a), -4); auto mid_b = b.begin() + (b.end()-b.begin())/2; iota(b.begin(), mid_b, -(n/2)); iota(mid_b, b.end(), 1); say("a\%b"); show_func_result_table(a, b, mymod); say("----------------------------------"); say("a/b"); show_func_result_table(a, b, mydiv); say("----------------------------------"); say("a"); show_func_result_table(a, b, mynum); return 0; }
結果:
bash-3.2$ g++ --version Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) Target: x86_64-apple-darwin14.4.0 Thread model: posix bash-3.2$ g++ ./main.cpp -std=c++11 -o main.out bash-3.2$ ./main.out a%b b\a| -4 -3 -2 -1 0 1 2 3 4 5 ================================== -5| -4 -3 -2 -1 0 1 2 3 4 0 -4| 0 -3 -2 -1 0 1 2 3 0 1 -3| -1 0 -2 -1 0 1 2 0 1 2 -2| 0 -1 0 -1 0 1 0 1 0 1 -1| 0 0 0 0 0 0 0 0 0 0 1| 0 0 0 0 0 0 0 0 0 0 2| 0 -1 0 -1 0 1 0 1 0 1 3| -1 0 -2 -1 0 1 2 0 1 2 4| 0 -3 -2 -1 0 1 2 3 0 1 5| -4 -3 -2 -1 0 1 2 3 4 0 ---------------------------------- a/b b\a| -4 -3 -2 -1 0 1 2 3 4 5 ================================== -5| 0 0 0 0 0 0 0 0 0 -1 -4| 1 0 0 0 0 0 0 0 -1 -1 -3| 1 1 0 0 0 0 0 -1 -1 -1 -2| 2 1 1 0 0 0 -1 -1 -2 -2 -1| 4 3 2 1 0 -1 -2 -3 -4 -5 1| -4 -3 -2 -1 0 1 2 3 4 5 2| -2 -1 -1 0 0 0 1 1 2 2 3| -1 -1 0 0 0 0 0 1 1 1 4| -1 0 0 0 0 0 0 0 1 1 5| 0 0 0 0 0 0 0 0 0 1 ---------------------------------- a b\a| -4 -3 -2 -1 0 1 2 3 4 5 ================================== -5| -4 -3 -2 -1 0 1 2 3 4 5 -4| -4 -3 -2 -1 0 1 2 3 4 5 -3| -4 -3 -2 -1 0 1 2 3 4 5 -2| -4 -3 -2 -1 0 1 2 3 4 5 -1| -4 -3 -2 -1 0 1 2 3 4 5 1| -4 -3 -2 -1 0 1 2 3 4 5 2| -4 -3 -2 -1 0 1 2 3 4 5 3| -4 -3 -2 -1 0 1 2 3 4 5 4| -4 -3 -2 -1 0 1 2 3 4 5 5| -4 -3 -2 -1 0 1 2 3 4 5
-1%2
は 1 になって欲しいなあ😩