先说说十进制减法,当被减数各列比减数各列小时,就需要从高位借个1过来,比如110-21=89,由于0小于1因此从上一位借1变成10-1=9,然后高位变成10-2=8,最终结果就是89。
假设最多是3位数的减法,为了不产生借位可将原表达式变成a-b=a-b+1000-1000=a-b+999+1-1000=a+(999-b)+1-1000。
那么110-21=110+(999-21)+1-1000=110+978+1-1000=1088+1-1000=1089-1000=89;
如果是21-110=21+(999-110)+1-1000=21+889+1-1000=910+1-1000=911-1000;此时产生了借位,如果将原式变成a-b=a-b+999-999后可得21-110=910-999再将910和999两数颠倒解得89,最后取89的负数就不会产生借位了。
二进制的处理技巧与之类似,比如就进行8位二进制的减法,a-b=a-b+256-256=a-b+255+1-256=a+(255-b)+1-256。
110-》0110_1110,21-》0001_0101, 110-21=0110_1110+(1111_1111-0001_0101)+0000_0001-1_0000_0000=0110_1110+1110_1010+0000_0001-1_0000_0000=1_0101_1001-1_0000_0000=0101_1001=89。
对于21-110=0001_0101+(1111_1111-0110_1110)+0000_0001-1_0000_0000=0001_0101+1001_0001+0000_0001-1_0000_0000=1010_0111-1_0000_0000到这一步时同样会产生借位的情况,此时需要类似于十进制的处理方法将原式变成a-b=a-b+255-255=1010_0110-1111_1111再将1010_0110和1111_1111颠倒解得0101_1001,最后取0101_1001的负数可得-89。由于有些小技巧至于如何取负数将在下篇说明。
最终看来减法的步骤比加法要繁杂点,按理减法的运行速度要慢于加法。实际亲测之后,也印证了改结论,代码如下:
public static void main(String[] args) {
// TODO Auto-generated method stub
long start = System.currentTimeMillis();
int k=0;
for(long i=0;i<10000000000l;i++) {
//(1)
k-=i;
}
long end = System.currentTimeMillis();
System.out.println(end-start);
}
可以在(1)位置处改变符号进行测试,本人测得的结果是加法的效率会比减法快近1倍左右,值得注意的是对于自增和自减效率并不大,可能是系统作了优化。