闲着没事研究了下二进制减法。
二进制加法都知道吧,就是异或+进位。
$$
\text{binaryAdd}(a, b) =
\begin{cases}
a & \text{if } b = 0, \\
\text{binaryAdd}(a \oplus b,\ (a \land b) \ll 1) & \text{otherwise.}
\end{cases}
$$
那么同理可得
$$
\text{binarySub}(a, b) =
\begin{cases}
a & \text{if } b = 0, \\
\text{binarySub}(a \oplus b,\ (\neg a \land b) \ll 1) &
\text{otherwise.}
\end{cases}
$$
大夫真是妙手回春啊!
虽然真正计算机中是用补码+加法器直接实现的()
注: - $ $ 代表 ^
,按位异或 - $ $ 代表
&
,按位与 - $ $ 代表 ~
,按位非 - $ $ 代表
<<
,左移
C++ 实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #include <iostream> #include <string> #include <cmath>
void showBinary(const std::string& _, int x, const size_t& digits){ std::string b; while(x){ b += '0'+(x&1); x >>= 1; } while(b.length()<digits) b += '0'; for(size_t i=0; i<(b.length() / 2);i++){ std::swap(b[i], b[b.length()-i-1]); } std::cout << _ << " = " << b << std::endl; }
int main(){ std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); int a, b, c; std::cin >> a >> b; size_t s = std::max((int)log2(a)+1, (int)log2(b)+1); std::cout << "s = " << s << std::endl; showBinary("a", a, s); showBinary("b", b, s); while(b){ c = a^b; showBinary("a", c, s); b = ((~a)&b) << 1; showBinary("b", b, s); a = c; } std::cout << a; return 0; }
|