关于高精度

来源:互联网 发布:如何分析薪酬数据 编辑:程序博客网 时间:2024/04/27 17:40

关于高精度

                                                                                                  作者:焦祺         08-11-8

 

所谓的高精度运算,是指参与运算的数(加数,减数,因子……)范围大大超出了标准数据类型(整型,实型)能表示的范围的运算。

高精度的特征使我们在运用上一般会借助函数模板,不过在有的情况是需要我们更改的,所以高精度的计算还是值得我们深入研究。

 

高精度计算的一般分类:

l  高精度加法

l  高精度减法

l  高精度乘法(阶乘)

l  高精度除法(求余)

l  高精度数比较

 

高精度加法计算原理:

观察人工计算的方法:竖式加法

       223

+     996

-----------

         9       3+6=9

        1          2+9=11,当前位1,进位1

       2            2+9+1=12,当前位2,进位1

  1               进位的1

-----------

   1219      

 

 

算法框架:

A为AN位数,B为BN位数,结果存到C

N=AN>=BN?AN:BN;//求得两数的高位

for(从个位开始 TO 两数最高位N)

{

        C的第i位 = A的第i位 + B的第i位

        进位位 = C第i位 / 10

        当前位的值 = C第i位 %10

}

 

自编高精度加法函数模板:

 

 

 

加法输出函数:

 

 

 

高精度加法计算的时间效率提高方法:

 

在运用中,加法的高精计算算是比较简单,用起来也比较那灵活多变一点,在简单的题目中可以用二维数组计算打表。这样不用每次都要去调用高精度加法函数,从而可以提高实战中的时间效率。

 

如:HDOJ1715 ( 大菲波数 )

 

 

 

以上的方法可以较好的解决时间效率的问题,但在有些运用中,空间效率却成为考点,由于计算高精度常用INT数组,所以优化时就要在数组上下功夫了。

如:HDOJ1250 ( Hat's Fibonacci )

 

 

高精度减法计算原理:

 

竖式减法:

       927

-      896

-----------

         1        7-6=1

        3          12-9=3,借位12

       0            (9-1)-8=0

-----------

         31

 

注意:

注意减法的特性:借位
不要忽略连续借位!
借位前被借位是0的情况
注意可能出现负数!
前导零处理
 

 

 

 

算法框架:

 

for(从个位开始 TO 两数最高位N)

{

              if(a的第i位小于b的第i位)     

              {//那么需要借位

                     借位位减1

                     当前位加10

              }

       a第i位和b第i位的差存入a;

}

 

自编高精度减法函数模板:

 

 

 

 

比较函数:

 

高精度乘法计算原理:

 

竖式乘法:

1. 大数乘小数,比如12345*9=?

 1 2 3 4 5

*          9

--------------

           45           5*9=45

    36                4*9=36

  27                    3*9=27

18                        2*9=18

+     9                          1*9=9

--------------

1 1 1 1 0 5

 

2. 大数乘大数,比如12345*12345=?

12345*12345=12345*5+

               12345*4*10+

               12345*3*100+

               12345*2*1000+

               12345*1*10000

问题转化为若干个大数乘小数之和

 

算法框架

用一个i,j二重循环{{res[i+j]+=b[i]*a[j];}}

//不管三七二十一先把结果算出来

//然后我们再来考虑进位:

for(……)

{

如果:res[i] >= 10

那么:

res[i+1] += res[i]/10; //进位位

res[i] %= 10;        //原始位

}

 

自编高精度乘法函数模板:

 

 

 

乘法输出函数:

 

 

 

 

高精度除法计算原理:

 

竖式除法----用多次的减法来实现!

             36

12345 √ 452678

         37035      12345*3=37035

          8232        45267-37035=8232

          82328      下一位再次减法

          74070      12345*6=74070

           8258      82328-74070=8258 余数

 

高精度除以低精度算法框架

d = 0

for(从除数的最高位 to 除数的个位)

{

       d += a的第i位

       计算d和除数的商 存入C数组中

       计算d和除数的余数 存入d中

     处理该位的余数便是下一位的十位

}

 

自编高精度除以低精度函数模板:

 

 

 

 

高精度除以高精度算法框架

d=0;//余数

for(从除数的最高位 to 除数的个位)

{

     d自乘10     //高精度乘10

     被除数的第i位加入d中

     while(d大于除数)

    {

          d和除数的差存在d中

          商++;

     }

}

 

高精度除法函数模板:

 

  

 

高精度阶乘函数模板:

 

语法:int result=factorial(int n);

参数:

n:n 的阶乘

返回值:阶乘结果的位数

注意:

本程序直接输出n!的结果,需要返回结果请保留long a[]

需要 math.h

源程序:

  

 

 

 

PKU上关于高精度的题目汇集:

1001(高精度乘法) 2413(高精度加法,还有二分查找)

1220, 1405, 1503, 1131, 2305,2325,2389,1604,1047

1504 1517 1519 1547 1552 1563(考虑仔细一点,还要注意精度)

2381 2385 2393 2394 2395 2413(高精度基础) //2418 2419

 

 

参考文献:

 

《程序设计基础第2版》吴文虎 清华大学出版社

《ACM程序设计培训教程》      中国铁道出版社