导线平差精度的控制的研究与实现

    在导线平差中,对于double型数据,在计算过程中存在数据的丢失,会导致结果不准确。而平差对于精度的要求比较高,在工程应用中,这也是一个亟需解决的问题。本文研究是为了解决double型的加减运算时的精度无法控制的问题,按照本文所设计的算法可以使计算结果可以精确到小数点后6位。

1.     基本思路

分别写一个加法和减法的方法,将两个double型的数据的每一位一一取出,放在数组中,再对两数相应的位一一进行加减运算,最后将计算的结果数组转化为double型的数据返回。

2.   具体实现

2.1 读取数据

对于两个double型的数据,先将其每一位一一取出。对于整数部分,可采用“/取整运算符除以101001000等得到。

例如:若有数据double n=123.456, 定义存放整数部分数据的数组为 int integer_n[100],则其第i位的数为integer_n[i]= n/pow(10,i),这一语句只能取出数据的最高位。但还需要再设一个辅助变量数组double oddinteger_n[100],而oddinteger_n[i]= (oddinteger_n[i+1]-integer_n[i+1]*(pow(10,i+1))),对于取数据的非最高位,integer_n[i]=oddinteger_n[i]/pow(10,i),表示若取出最高位1后,oddinteger_n[i]的值为23.456,此时integer_n[i]的值为2,依次进行下去。

但是,对于小数部分,需要另外写一个循环,比较麻烦。因此,可以将n转化为一个小数部分为0的数,在一个循环内将其数据全部取出。即n=n*pow(10,6)n的小数部分有6位)。此过程的具体代码如下(包含整个方法所有的变量的定义):

       int integer_n[100];         //n的整数部分

       int integer_m[100];        //m的整数部分

      double oddinteger_n[100];  //n的整数部分辅助变量

       double oddinteger_m[100];  //m的整数部分辅助变量

       int addalone[100];         //每位的和

       double add[100];          //求和辅助变量

       double sum=0.0;          //最终结果

 

       n=n*pow(10,6);          //n化为整数

       m=m*pow(10,6);         //m化为整数

 

       for(int i=15;i>=0;i--)      //nm的整数部分一一取出

       {

              if(i==15)           //最高位单独取出

              {

                     integer_n[i]=n/pow(10,i);

                     oddinteger_n[i]=n;

                     integer_m[i]=m/pow(10,i);

                     oddinteger_m[i]=m;

              }

              else                 //取出其它位

              {    

                     oddinteger_n[i]= (oddinteger_n[i+1]-integer_n[i+1]*(pow(10,i+1)));

                     integer_n[i]=oddinteger_n[i]/pow(10,i);

                     oddinteger_m[i]= (oddinteger_m[i+1]-integer_m[i+1]*(pow(10,i+1)));

                     integer_m[i]=oddinteger_m[i]/pow(10,i);

              }

2.2 加法的实现

实现加法运算时,将两数的每一位一一相加,从最低位开始。计算加法时,需要考虑进位的问题。当相加的和大于9时,就需向前进一位,即循环体中下一次求和时还需加进位数,且当前数据需减10。这一过程比较繁琐,需要在两个循环体中进行。具体代码如下:

for(int j=0;j<=15;j++)                 //nm的每一位相加

       {

              if(j==0)                     //最低位相加

              {

                     addalone[0]=integer_n[0]+integer_m[0];

              }

              else                         //其它位相加

              {

                     if(addalone[j-1]>9)         //前一次求和大于9时,此次需加1

                     {

                            addalone[j]=integer_n[j]+integer_m[j]+1;

                     }

                     else                      //无进位时正常求和

                     {

                            addalone[j]=integer_n[j]+integer_m[j];

                     }

              }

       }

       for(int j=0;j<=15;j++)               //求出最后的和

       {

                     if(addalone[j]>9)           //若有进位,则需减10

                     {

                            addalone[j]-=10;

                     }

//将每一位求和的数组整体转换为一个double型的数据

                     if(j==0)

                     {

                            add[j]=addalone[j];

                     }

                     else

                     {

                            add[j]=add[j-1]+addalone[j]*(pow(10,j));

                     }

       }

 

sum=add[15]*pow(10,-6);                    //add[15]即为此次结果,将其还原为有6位小数的数据,即为最终的求和结果

return sum;                                 //为了获取到求和的结果,最后需返回“sum

2.3 减法的实现

实现减法运算时,将两数的每一位一一相减,从最低位开始。计算减法时,需要考虑借位的问题。而且由于减法有正负的问题,需要比较两数的大小后分两种情况考虑。具体代码如下:

if(n>=m)                                 //nm大时

       {

              for(int j=0;j<=15;j++)                //nm的每一位相减

              {    

                     if(integer_n[j]>=integer_m[j])      //如果n的当前位大于m,正常相减

                     {

                            addalone[j]=integer_n[j]-integer_m[j];

                     }

else                             //n的当前位小于m,则需借位,且被借位要减1

                     { 

                            addalone[j]=integer_n[j]-integer_m[j]+10;

                            integer_n[j+1]=integer_n[j+1]-1;

                     }

              }

       }

      

if(n<m)                                     //nm小时,用m n,再在所求得的数前加“-

       {

              for(int j=0;j<=15;j++)                  //mn的每一位相减

              {    

                  if(integer_m[j]>=integer_n[j])        //如果m的当前位大于n,正常相减

                     {

                            addalone[j]=integer_m[j]-integer_n[j];

                     }

else                         //m的当前位小于n,则需借位,且被借位要减1

                     { 

                            addalone[j]=integer_m[j]-integer_n[j]+10;

                            integer_m[j+1]=integer_m[j+1]-1;

                     }

              }

       }

       for(int j=0;j<=15;j++)                //求出最后的和(与加法运算时的基本相同)

       {

              //if(addalone[j]>9)

              //{

              //     addalone[j]-=10;

              //}

 

              if(j==0)

              {

                     add[j]=addalone[j];

              }

              else

              {

                     add[j]=add[j-1]+addalone[j]*(pow(10,j));

              }

       }

//将结果还原为有6位小数的数据,即为最终的求差结果

       if (n>=m)                          //

       {

              sum=add[15]*pow(10,-6);

       }

       if (n<m)

       {

              sum=-add[15]*pow(10,-6);       //n小于m,在最终结果前加“-

       }

return sum;                                 //为了获取到求和的结果,最后需返回“sum

3.     结论

本文解决了全站仪导线平差中的加减法中数据丢失的问题,对精度的控制也有了一定的提高。但是仍存在着一些问题,如只能精确到小数点后6位,没有解决乘除的精度控制等,这将会在以后的工作中进行改进。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值