大数除法之估商法

我用VB完整的实现了估商法,支持正负,小数,科学计数法,之所以说完整实现,是因为这个程序是我写的(落叶高精度表达式计算机)的子程序,能够和其它计算程序配合,实现高精度加减乘除,阶乘,乘方,开N次方,函数等混合运算.
例:能够运行万位精度,开10000次方根正确运算,开N次方根是用的迭代法,为什么举这个例子,因为参入运算的子程序如果有问题,是计算不出正确结果的,现在这个计算机已完善:

 

另外我再谈谈我对除法的一些看法,不能利用计算硬件的算法不是好算法,所以设计算法时要充分考虑硬件的效能,这里可以理解为大进制数比小进制数效率更高,当然这个进制的基数不要超过cpu位长的二分之一,例万进制要比十进制数运算更快。例:采用百进制时,12*34需要一次乘法运算,而采用十进制时需要4次乘法运算。

 

简单说一下我知道的一些大数除法算法,

第一:用减法实现,从高位向低位减,我最早用的是这个方法并实现,该方法效率低下;

第二:试商法,针对十进制数,从0-9试商,或按二分法试商,效率稍高,试商法也是一个效率低下的方法;

第三:是一个论文上说的方法,用的是十进制,保存除数和1-9相乘的得数,其它步骤和估商法差不多,这个方法因为预算了除数和商的值,省除了后面的乘法重复运算,但当采用万进制等大进制数时,这个方法不适用;

第四:估商法(不是试商,试商非常慢),整理除数,利用被除数和除数的前几位估出一个不小于正确商的数,做乘法,再大数减,判断是否发生借位(不是用cpu的借位标志判断),若产生借位,商减一,余数加一次除数,判断余数和除数的大小,进入相应的步骤....,速度还满意;

第五:迭代法,对于大长度数运算超快!

这里我先讲一讲我的估商算法,我所采用的数使用万进制表示,我的估商算法单就估商环节已经比较完美了。估商法的基本实现原理就是模拟我们常用的笔算除法,在采用大进制数进行运算时,估商的准确度决定了这个算法的效率。

(提高精度的基本原则: 
  一般的,对于乘法和除法。如果希望结果精确到n比特,两个源操作数至少包含n比特数据。所以,为了估商准确,我们总是尽可能让更多的比特参与运算。)这段话是一个高手对外国文献的解析,可以作为如何提高估商精确度和高精运算的理论指导。

下面是我从另一个角度叙估商的原理:

第一步:除数整理,就是把除数乘以一个数(1-9),使这个除数尽量接近你所采用的进制的最大值,2^32进制时,就是65535,万进制就是10000

Knuth(高德纳)对估商做出了一个数学推导,公式一大堆,一句话,就是左移除数,乘2乘2...,例:0011 0101 左移成1101 0100,当时硬件差,他以左移替代乘法,估商误差平均2次中误差1次,这种算法最佳实现是一次单精对多精乘法,一次多精减法,50%错误修正(具体怎么修正,各有各的算法,我的算法是商减一,余数加一次除数);总的思路就是整理除数。

我在推算估商算法时也发现了类似方法(当时没查到上面所述资料),我的方法也是整理除数,但我是以万进制为基作调整,

举例:万进制时:下面的例子中因被除数第一位小于除数第一位,合并被除数第一位和第二位,整除除数第一位估商,如下:
0999 5678 1000/1000 9999 ,估商9995,正确商为9985,把被除数,除数乘9,8996 1102 9000/9008 9991,估商9986,另外被除数变了有没有影响,但综合下来影响很小,经测试除数整理好后,估商误差比Knuth(高德纳)的方法小,我也是不明白,老K的主思路和我一样,为什么误差要大些,最后发现原因就在于左移,只有乘2,乘4,乘8,除数没有调整到最佳状态,为什么这么说呢?
如果一个除数需要调整,乘以3最合适,按老K的算法你就只能乘2了,或乘4了。我觉得老K的左移操作对用数据头表示的高精度数没多大用处,向这种左移右移的操作,在数据头里把指数改一下就可以了,如万进制:1234*0100,只需要把1234的指数位加2就行了
详细说一下我的除数整理算法:
0999 5678 1000/0010 0099,除数乘100(不是真乘,只是调整数的位长度,和小数点位置),jw=2(这个用于后面调整小数位),变成0999 5678 1000/1000 9900,用(1000 9900)*1-9

 

从小向大试,找出一个最大的数,使它俩的积不超过100000000,这里是9,把被除数,除数乘9,好吧,除数整理已完成,进入主程序。

 

第二步:估商算法,

有一个估商算法用被除数的前三个进制位(这里假设万进制时:一个进制位为四位)除以除数的前两个进制位估商,估商精度要高于Knuth(高纳德)的算法,不过32位机存不下三个进制位,要单独处理,我放弃了,后来我又重新思考这个问题,得出如下结论:估商时并不一定要用三个进制位,估四位商时,参入估商的除数位大于四位时,可以大大增加正确率,

下面这个是我的估商源码: 
方法一:ysjg(i) = yShu(2) \ b(2)        ‘ysjg(i)存放估出的商, yShu(2)存放被除数的前8位, b(2) 存放优化过的除数前四位,估商误差小于50%,只是粗略估计,没有数学论证;
这个是我借鉴上述结论后改进的代码:
方法二:ysjg(i) = (yShu(2) * 10 + yShu(3) \ 1000) \ (b(2) * 10 + b(3) \ 1000),现在估商误差5.2%,每计算出2500(相当于一万位)个万进制得数,估商错误修正函数运行130次左右(商减一修正),上式实际上是9个十进制位除以5个十进制位获得4个十进制位的商。

现在估商误差已经很小,甚至可以忽略不计

估商的误差主要是除数第二个进制位的进位造成的,当第二个进制位全部为零时,估商准确率接近百分之百,例:22220000,因为是进位造成的误差,所以我们用整除方式估商时,错误的商只会大于正确商,所以采用(商减一修正,一般只需要修正一次就能得到正确值)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值