发新帖我要提问
12
返回列表
打印

N位压缩BCD加法

[复制链接]
楼主: 雁舞白沙
手机看帖
扫描二维码
随时随地手机跟帖
21
hotpower| | 2007-3-13 18:47 | 只看该作者 回帖奖励 |倒序浏览

哈哈~~~第24行才真正是程序的"精华"~~~





Sum = One + Two + Sum;//二进制求和(注意上次低位向高位的进位)
Tmp = (One & 0xf0) + (Two & 0xf0);//为半进位做准备


if ((Tmp != (Sum & 0xf0)) //判断半进位,即D3向D4的进位,例如8+9=17->0x11,不判将为0x01
   || ((Sum & 0x0f) > 9))//上句若无半进位,还要考虑BCD<=9的问题 
{
   Sum += 6;//BCD码低4位调整,哈哈~~~这句在教课书里都有的~~~
}
if (Sum >= 0xa0) {//BCD码高4位调整
  Sum += 0x60;//注意"混球"~~~
}

使用特权

评论回复
22
xwj| | 2007-3-13 18:48 | 只看该作者

18楼请看仔细点哦,到底有没有半进位和全进位:-)

看到那个over变量是用来做什么的吗?

使用特权

评论回复
23
lenglx| | 2007-3-13 19:07 | 只看该作者

呵呵,表示抱歉

没仔细看

使用特权

评论回复
24
xwj| | 2007-3-13 19:17 | 只看该作者

关于24行

    Sum = One + Two + Sum;//二进制求和(注意上次低位向高位的进位)
    Tmp = (One & 0xf0) + (Two & 0xf0);//为半进位做准备这句为什么不把之前的Sum尾数加上仪器判断?当然,要放在上一句前面
    if ((Tmp != (Sum & 0xf0)) || ((Sum & 0x0f) > 9)) {//BCD码低4位调整
      Sum += 6;//凡加减10或9的都是"混球"~~~
    }

比如这样写:
  while(DataLend) {//不能DataLend--或--DataLend
    DataLend --;//调整到正确的数组位置
    One = DataOneDptr[DataLend];//取出正确的被加数
    Two = DataTwoDptr[DataLend];//取出正确的加数
    Tmp = (One & 0x0f) + (Two & 0x0f) +(Sum & 0x000f);//为半进位做准备--计算低4位以得到半进位
    Sum = One + Two + Sum;//二进制求和(注意上次低位向高位的进位)
    if (Tmp > 9)) {//BCD码低4位调整
      Sum += 6;//凡加减10或9的都是"混球"~~~--以16为模,加6和减10是一回事,因为我另外记录了进位状态,只有你这看不到那才是混球啊
    }

    if (Sum >= 0xa0) {//BCD码高4位调整
      Sum += 0x60;//注意"混球"~~~
    }


哼!
以前编俄罗斯方块那么复杂的位碰撞和换行都想明白并全部用位运算处理好了,现在还会在这么小儿科的问题上翻船?

使用特权

评论回复
25
hotpower| | 2007-3-13 19:29 | 只看该作者

哈哈~~~看到10就是不舒服~~~再发以前的PIC宏定义

一直没用PIC了,刚找到.
如果下午找到了,算法可能更简单~~~

一会用"红杏出墙记"编个更"混球"的~~~
相关链接:http://www.**/blog/hotpower/18017/message.aspx

使用特权

评论回复
26
hotpower| | 2007-3-13 19:39 | 只看该作者

我又该倒塌了~~~+(Sum & 0x000f)绝对是"混球"~~~

(One & 0xf0) + (Two & 0xf0)表示只计算结果的高4位.
即结果为低4位为0,而Sum在此处为0或1,肯定不能影响高4位.

+Sum在Tmp != (Sum & 0xf0)中被搞掉了.

使用特权

评论回复
27
xwj| | 2007-3-13 19:49 | 只看该作者

关于加6还是减10的问题

由于BCD是以每4位代表一个数字,10进制,超过9就进位,而对于BCD加法(不是十六进制加法),最大只可能是9+9=18=0x12,转成BCD是0x18,半进位的值只能是1或0

如果我们加上6,就会得到0x18,对于需要的后4位,还得屏蔽高4位(&0x0f),这时进位在高4bit里;
而用减10的方法,就会得到0x08,这4位已经是我们需要的结果,就可以省掉屏蔽高4位的步骤,节约一点时间

而我们判断进位时(不管加6还是减10都要判断的),就已经知道半进位了,半进位的值只能是1或0,如果是汇编,用CY的话下面半字节可以直接用ADDC来算,那就更快了;但C下加位变量会做类型转换,还不如用1字节来表示1和0方便、通用,这一步用掉了加6方法省掉屏蔽高4位节约的时间,实际上也就差不多的--既不会比他快也不会比他慢,但半进位标志更明显了(用汇编的话减10会更快)




使用特权

评论回复
28
xwj| | 2007-3-13 19:57 | 只看该作者

再说HotPower的程序为什么会慢一些和大一些

因为他用了双字节加法!

对于8位的51,除了汇编下用DPTR加1是双字节运算外,其他的都只有单字节运算指令,

如果多余一字节,则必然要多进位判断和运算;
而如果不足一字节,又必然增加屏蔽无关位的指令。
--这些都会增加指令和时间,因此只有尽量用处理器本身能字节运算的字长来计算才是最快的(对于51就是8位了)

使用特权

评论回复
29
xwj| | 2007-3-13 20:01 | 只看该作者

哈哈,和HotPower这样的高手“掐架”还是挺过瘾的,等你出招

使用特权

评论回复
30
hotpower| | 2007-3-13 20:20 | 只看该作者

实际上我期待邓苗同志出手才算热闹~~~

搞不好他来个挑战咱们全下岗~~~

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则