第二十一节 通过加减法高效的求出两个无符号整数的商和余数

  

    假设处理器不能实现除法运算,通过加减法高效地求出两个无符号整数的商和余数。  事实上,在微处理器上,所有的四则运算都会转化为加法,但是除法运算会消耗掉微处理器大量的时间,因此我们设计一个算法,只通过加减法求出两个无符号整数的商和余数。这个题目广州致远电子有限公司曾经用来作为招聘软件工程师的机试题目。说起周立功,首先确实得感谢他,从大一暑假开始就给我提供夏令营机会在广州致远电子有限公司实习,将软件功底一次次提升,去年7月份开始更和致远签下合同,开始正式实习之路。但是11月份,由于个人想法,依然离开了广州致远。扯远了,拉回来。
算法一:用被除数(iDividend)循环去减除数(iDivisor),直到被除数减去除数的差(记录为iRemainder)小于除数为止。做减法的次数(记录为iCompany)即为商,iRemainder即为余数。但是当被除数比除数大很多时(iDividend=10000 iDivisor=3),相减的次数达3333次,所以此方法非常低效。
算法二:使用递归算法实现。除数(iDivisor) =除数(iDivisor)*2。因此,商(iCompany)= (iCompany)*2。如果余数大于除数,则商(iCompany)= (iCompany)+1,余数(iRemainder)= 余数(iRemainder)- 除数(iDivisor)。假设被除数(iDividend) =100除数(iDivisor)=3,则递归算法求商和余数过程。
很显然,算法一效率太低,不可取,因此选择算法二。
    采用算法二,就涉及到返回值的传递,方法有四种:
作为返回值的商和余数,如何传回给主函数?这是一个很有讲究的问题,方法很多,可以是用过指针传回,可以通过全局变量,可以通过结构体,可以使指针函数等。
方法一:全局变量,一个程序中出现全局变量是很难让人接受的,这里使用全局变量返回时不可取的。
  2.1  程序流程图
方法二:结构体,结构体确实可以保存很多变量,并且传回来也是没有问题的。但是结构体所占内存较大,不提倡使用。
方法三:指针,在递归函数中,使用指针变量将值返回。
方法四:指针函数,在递归函数中将商和余数的值返回。
对比上面四种方法,从程序健壮性、可移植性、安全性等诸多方面考虑采取方法三或方法四。

递归函数的声明,采用指针变量返回商和余数。
/*******************************************************************************
** 函数名称:pass_to_return
** 函数功能:递归算法
** 入口参数:unsigned int pDividend  ,  unsigned int pDivisor
**           unsigned int *iCompany , unsigned int *iRemainder
** 出口参数:
*******************************************************************************/
extern unsigned int
pass_to_return( unsigned int iDividend , unsigned int iDivisor,
             unsigned int *iCompany , unsigned int *iRemainder) ;


递归函数的详细设计,采用指针变量返回商和余数。
/*******************************************************************************
** 函数名称:pass_to_return
** 函数功能:递归算法
** 入口参数:unsigned int pDividend  ,  unsigned int pDivisor
**           unsigned int *iCompany , unsigned int *iRemainder
** 出口参数:
*******************************************************************************/
unsigned int pass_to_return( unsigned int iDividend , unsigned int iDivisor,
                             unsigned int *iCompany , unsigned int *iRemainder)
{
         
         /*
         *  如果被除数(iDividend)小于除数(iDivisor)
         *  则商(iCompany)0,余数(iRemainder)为被除数(iDividend)
         */
         if( (iDividend) < (iDivisor) ){
                  
                   *iCompany    = 0 ;
                   *iRemainder  = iDividend ;
                  
         }  
         
         /*
         *  如果被除数(iDividend)等于除数(iDivisor)
         *  则商(iCompany)1,余数(iRemainder)0
         */
         else if( (iDividend) == (iDivisor) ){
                  
                   *iCompany    = 1 ;
                   *iRemainder  = 0 ;
                  
         } else{
                  
                   /*
             *  如果被除数(iDividend)大于除数(iDivisor)
             *  进行递归调用
             */
            
                   /*
                   * 返回递归函数
                   */      
    pass_to_return( iDividend , (iDivisor+iDivisor) ,
                        iCompany , iRemainder ) ;
                                          
             /*
                   *   = 2*
                   */
                   *iCompany +=  *iCompany  ;
            
             /*
                   *  如果余数 (*iRemainder) 大于 除数(iDivisor)
                   */
             if( (*iRemainder) >= iDivisor ){
               
               /*
                            *  则商=+1
                            */
               *iCompany += 1 ;
               /*
                            *  余数=余数-除数
                            */
               *iRemainder = *iRemainder - iDivisor ;
               
    }
         
         }
         
         return 0 ;
         
}

你可能感兴趣的:(c学习)