1 .在概要计算机上,加减法由CPU实现,每次运算时将数据加载到内存,处理后将结果写入内存因为计算机只识别0和1,所以所有运算都是以二进制格式进行的。 两个数的相加直接在两者的补码上相加。 使用补数的理由是,1 .将正数的符号位转换为1以表示负数的加法结果不正确。 2 .正数的原码、反码、补码相同。
2 .正数原码、反码、补码以8位CPU为例,+1的原码、反码、补码均为0000 0001,如此
在此补充,8位的有符号二进制正数的范围为http://www.Sina.com/0000001 (20=1(2^ {0}=) 结果为0000 0000,-0即- 128 (-127-1=http://www.Sina.com/000001http://www.Sina.com/11111111 10000000 8位0二进制0范围为http://www.Sina.com/1111111((27 ) )-(2^ {7) 0000001((2)=1(-)2^{0} )=-1 ) 20 ) 1两个特殊的0,0 (3358 www.Sina.com/000000 )和-0) 3358 www.Sina.com
3 .负数原码、反码、补码以8位CPU为例,1的原码为: http://www.Sina.com/0000001http://www.Sina.com 1111110http://www.Sina.com/的补码)反码1 )为http://www.Sina.com/1111113358 www .
g> 4.用python来模拟计算机的加减法过程 4.1加法 class TailRecursive(object): """ tail_recursive decorator based on Kay Schluehr's recipe http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496691 with improvements by me and George Sakkis. """ def __init__(self, func): self.func = func self.firstcall = True self.CONTINUE = object() # sentinel def __call__(self, *args, **kwd): CONTINUE = self.CONTINUE if self.firstcall: func = self.func self.firstcall = False try: while True: result = func(*args, **kwd) if result is CONTINUE: # update arguments args, kwd = self.argskwd else: # last call return result finally: self.firstcall = True else: # return the arguments of the tail call self.argskwd = args, kwd return CONTINUE# recursion version# @TailRecursivedef add(a, b): if b == 0: return a sum = a ^ b # xor implements addition which not including carry carry = (a & b) << 1 # carry return add(sum, carry)print(add(3, 3))"""tail recursion -> iterationyou can also use the decorator: @TailRecursive"""# iteration versiondef add2(a, b): sum = 0 carry = 0 while(b): sum = a ^ b carry = (a & b) << 1 a = sum b = carry return a 4.2减法以下代码在进位的时候会一直增大,跳不出循环,有问题,有小伙伴能解决的嘛?,代码参考
def sub(a, b): if a >= b: return add2(a, add2(~b,1)) else: return add2(~add2(b, add2(~a, 1)), 1)print(sub(3, 1))----2021.4.1更新----
上面这个代码不能跳出循环的根本原因是:python中的int数据的位数是不固定的,所以不想c++有溢出操作。那我们的解决思路就是:使用& 0xFFFFFFFF来限制数据的范围到32位。此外,32位的最大正数为0x7FFFFFFF,即: 2 31 − 1 = 2147483647 2^{31}-1=2147483647 231−1=2147483647,如果输出 x x x 大于这个值,例如:0x080000000,即: 2 31 = 2147483648 2^{31}=2147483648 231=2147483648,则先做0x080000000 & 0xFFFFFFFF=0x07FFFFFFF,然后再做~0x07FFFFFFF=0xF80000000,即对应了最小负数 − 2 32 = − 2147483648 -2^{32}=-2147483648 −232=−2147483648,这样便完美解决了溢出问题。下面是改进的代码: