⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch24aok2.c

📁 稀疏矩阵、链表、图、队列、二叉树、多叉树、排序、遗传算法等的实现
💻 C
📖 第 1 页 / 共 5 页
字号:
    * a pointer to an array of INT. This array may be un-normalized. 
    * The second argument is a pointer to a pointer. This latter is  
    * not yet pointing to anything, but will (at the termination of  
    * this routine) be an array of INT. This will be a normalized    
    * copy of the first argument. If the first array is normal then   
    * this pointer is identical to the first. If the first argument  
    * is not normal, then a new array is allocated, and the first is 
    * de-allocated, and the incoming first pointer set to NULL       
    */
    
    if ((aUnNormal==NULL) || (aNormal==NULL) || ((*aUnNormal)==NULL))
    {
        /*
        * If any of the incoming pointers is NULL, or the first     
        * array does not exist, then indicate an error:            
        */
        iStatus = EXIT_FAILURE;
    }
    else
    {
        /*
        * We know that the incoming pointers are (apparently) OK, So 
        * set the initial outgoing value to be simply a copy of the  
        * incoming:                                                  
        */
        plNormal = *aUnNormal;

        /*
        * Determine how many words (INTs) in the first array we have 
        * to scan:                                                   
        */
        k = abs(**aUnNormal);
        if (**aUnNormal<0)
            iSign = -1;
        /* Number of these which are after the point:                 */
        n = (*aUnNormal)[1];
        /* Therefore the number which are before the point:           */
        b = k - n - 1;

        /*
        * If there is anything at all in the first array, then count 
        * the number of zero words with which it begins:              
        */
        if (b>0)
        {
            j = (*aUnNormal)[2];
            m = 0;
            for (i = 2; ((j==0)&&(i<=b)); i++)
            {
                j = (*aUnNormal)[i];
                if (j==0)
                    m++;
            }   /* end of "for/i" count loop of zero prefix words     */
        }       /* end of "if/then" there are places before the point */
        
        /*
        * At this point we know that 'm' contains a count of the     
        * number of zero words at the start of the UnNormal input.
        * Now count backwards (provided that there is something
        * following the point) up the array, counting the number
        * of zero words with which the array ends, after the point:
        */
        if (n>0)
        {
            j = (*aUnNormal)[k];
            mm = 0;
            for (i = 0; ((j==0)&&(i<n)); i--)
            {
                j = (*aUnNormal)[k-i];
                if (j==0)
                    mm++;
            }   /* End of "for/i" count loop of zero trailing words  */
        }       /* End of "if/then" there are places after the point */

        /*
        * So now in 'm' we have the count of the number of leading
        * words to omit, and in 'mm' we have the count of the trailing
        * words to omit. 
        * So we need to (a) allocate a new array, and (b) copy the   
        * old into the new, and (c) deallocate the old array:        
        */
        if ((m+mm)>0)
        {
            /* Allocate the new normal array:                         */
            k = abs((*aUnNormal)[0]) - m - mm;

            /* Note that a normal zero has at least one leading word: */
            /* do not normalize away all the digits!                  */
            if (k<=1)
            {
                k = 2;
                m--;
            }
            j = aAllocate(k, pplNormal);

            /* Copy the un-normal to the normal:                      */
            for (i=1; (i<(k+1)); i++)
            {
                j = i + m;
                *(plNormal + i) = (*aUnNormal)[j];
            }

            /* Set the sign in the new, remembered from the old:      */
            if (iSign<0)
                *plNormal = - (*plNormal);

            /* de-allocate the old un-normal:                         */
            free(*aUnNormal);

            /* And tell the caller this has happened:                 */
            *aUnNormal = NULL;

        }   /* end of "if/then" there was a necessity to allocate new */

        /* And point the caller to the new normalized value:          */
        *aNormal = plNormal;

    }       /* end of "if/else" incoming pointers were OK             */
    
    return iStatus;
}

/* Add an INT array to an INT array                                   */
int aAdd ( INT * aOne, INT * aTwo, INT ** aAnswer )
{
    /* This routine allocates space for the answer, which the caller  */
    /* must, at some time, release                                    */

    int iStatus = EXIT_SUCCESS;
    int i = 0;
    int j = 0;
    int k = 0;
    int iBefore = 0;
    int iAfter = 0;
    int iAllocateLength = 0;
    int iSign = 1;
    int bUseAdd = 1;
    INT carry = 0;
    INT * pInt;
    INT ** ppInt = &pInt;
    
    /*
    * This routine adds together two very large numbers. Each of the 
    * arguments is assumed to be in an array of INT. This routine    
    * allocates enough space for the answer, and computes the sum.   
    * The answer is normalized before returning to the caller.       
    */

    /*
    * Before performing the addition the numbers have to be aligned, 
    * so that the number of places after the point are the same for
    * both numbers. This means possibly extending the shorted number.
    */
    
    /* Test the incoming pointers for validity:                       */
    if ((aOne==NULL) || (aTwo==NULL) || (aAnswer==NULL))
    {
        /* At least one of the arguments was bad: indicate to caller: */
        iStatus = EXIT_FAILURE;
        return iStatus;
    }
    else
    {
        /*
        * How many places are before and after the point in each 
        * of the addends?
        */
        iAfter = max(aOne[1],aTwo[1]);
        iBefore = max (abs(aOne[0])-aOne[1],abs(aTwo[0])-aTwo[1]);

        /*
        * Compute the maximum length of the answer array. This caters
        * for the worst case of carry upwards from the top word:     
        */
        iAllocateLength = iBefore + iAfter + 1;

        /* Allocate enough space for the answer, but only point to it */
        /* locally:                                                   */
        j = aAllocate(iAllocateLength, ppInt);
        /*
        * Now set the number of places after the point in the answer to
        * be the maximum number of places af the two incoming addends:
        */
        *(pInt+1) = iAfter;

        /*
        * We need to look at the signs of the incoming arguments. If 
        * these are the same, then we simply add the arguments, as if
        * they were both positive, and give the answer that sign. If,
        * however, they differ in sign, then we force them both positive
        * and do a subtraction. After the subtraction we determine the
        * outgoing sign. Hence we call either "internalAdd" or "internal-
        * Subtract" to do the real calculation. Note that each of these
        * internal routines normalizes its answer before returning, so
        * we can just hand that answer back to the caller (after any
        * adjustment of sign).
        */

        if ((*aOne>0) && (*aTwo>0))
        {
            bUseAdd = 1;
            iSign = 1;
        }
        else if ((*aOne<0) && (*aTwo<0))
        {
            bUseAdd = 1;
            iSign = -1;
        }
        else
        {
            bUseAdd = 0;
            iSign = 1;
        }

        if (bUseAdd==1)
            j = internalAdd ( aOne, aTwo, ppInt );
        else
        {
            /*
            * We know that we have to subtract - these elements
            * differ in sign. Place the positive element first.
            * We do NOT compare the absolute or signed values of
            * the two arguments here (using aCompare) - we only
            * need to know their signs:
            */
            if (*aOne>0)
                j = internalSubtract ( aOne, aTwo, ppInt );
            else
                j = internalSubtract ( aTwo, aOne, ppInt );
            /*
            * Note that the sign will have been computed by the
            * internalSubtract routine, so there is no need to
            * alter it in this routine.
            */
        }   /* end of "if/else" we have to use internalSubtract */

        /* Correct the sign of the answer:                           */
        if (iSign<0)
            **ppInt = - (**ppInt);

        /* Tell caller the address of the answer:                     */
        aAnswer = ppInt;

    }       /* end of "if/else" incoming pointers were OK             */
    
    return iStatus;
}

/* Subtract an INT array from an INT array                            */
int aSubtract ( INT * aOne, INT * aTwo, INT ** aAnswer )
{
    /* This routine allocates space for the answer, which the caller  */
    /* must, at some time, release                                    */

    int iStatus = EXIT_SUCCESS;
    int i = 0;
    int j = 0;
    int k = 0;
    int iBefore = 0;
    int iAfter = 0;
    int iAllocateLength = 0;
    int iSign = 1;
    int bUseAdd = 1;
    INT carry = 0;
    INT * pInt;
    INT ** ppInt = &pInt;
    
    /*
    * This routine subtracts two very large numbers. Each of the 
    * arguments is assumed to be in an array of INT. This routine    
    * allocates enough space for the answer, and computes the difference.
    * The answer is normalized before returning to the caller.       
    */
    
    /* Test the incoming pointers for validity:                       */
    if ((aOne==NULL) || (aTwo==NULL) || (aAnswer==NULL))
    {
        /* At least one of the arguments was bad: indicate to caller: */
        iStatus = EXIT_FAILURE;
        return iStatus;
    }
    else
    {
        /*
        * How many places are before and after the point in each 
        * of the addends?
        */
        iAfter = max(aOne[1],aTwo[1]);
        iBefore = max (abs(aOne[0])-aOne[1],abs(aTwo[0])-aTwo[1]);

        /*
        * Compute the maximum length of the answer array. This caters
        * for the worst case of borrow upwards from/to the top word:     
        */
        iAllocateLength = iBefore + iAfter + 1;

        /* Allocate enough space for the answer, but only point to it */
        /* locally:                                                   */
        j = aAllocate(iAllocateLength, ppInt);
        /*
        * Now set the number of places after the point in the answer to
        * be the maximum number of places af the two incoming addends:
        */
        *(pInt+1) = iAfter;

        /*
        * We need to look at the signs of the incoming arguments. If 
        * these are the same, then we subtract the absolutely smaller
        * from the absolutely larger, and give the result the sign of
        * the absolutely larger. If the signs are different, then we
        * add together the absolute values, and give the result the
        * appropriate sign.
        */

        if ((*aOne>0) && (*aTwo<0))
        {
            bUseAdd = 1;
        }
        else if ((*aOne<0) && (*aTwo>0))
        {
            bUseAdd = 1;
        }
        else
        {
            /*
            * The signs are the same. Perform an internalSubtract
            */
            bUseAdd = 0;
            iSign = aAbsCompare ( aOne, aTwo );
            if (iSign<0)
            {
                /*
                * The first argument is smaller than the second. Take
                * the first from the second, and use the sign of the
                * second:
                */
                j = internalSubtract ( aTwo, aOne, ppInt );
                if (*aTwo<0)
                    *pInt = - *pInt;
            }   /* end of "if/then" first arg. is smaller than second */
            else if (iSign>0)
            {
                /* 
                * The first argument is larger than the second. Take
                * the second from the first, and use the sign of the
                * first:
                */
                j = internalSubtract ( aOne, aTwo, ppInt );
                if (*aOne<0)
                    *pInt = - *pInt;
            }   /* end of "if/then" first arg is larger than second */
            else
            {
                /*
                * This is the special case where we know that the two
                * arguments have the same sign AND are equal in magnitude,
                * so the answer is zero. We simply allocate a zero array
                * (which we have already done), and normalize it:
                */
                j = aNormalize(ppInt, ppInt);
            }   /* end of "if/else" arguments are equal and opposite */

            /*
            * We have the answer - return to caller, indicating failure
            * if detected:
            */
            if (j!=0)
                iStatus = EXIT_FAILURE;
            return iStatus;
        }   /* end of "if/else" perform internalSubtract */

        /*
        * If control falls through to here, then we have to
        * add the absolute values together, and take the 
        * sign of the first as the outgoing sign:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -