#include <stdlib.h>
/* 输出数的最大位数 */
#define MAX_LEN 200
/* 链表节点 */
typedef struct BIGINT_NODE
{
struct BIGINT_NODE *pPre;
struct BIGINT_NODE *pNext;
unsigned short usData;
}BIGINT_NODE_STRU;
/* 双向链表 */
typedef struct BIGINT
{
BIGINT_NODE_STRU *pHead;
}BIGINT_STRU;
/* 链表加入节点方式 */
typedef enum INSERT_METHOD
{
PRE,
NEXT
}INSERT_METHOD_ENUM;
int Init(BIGINT_STRU *pBigInt);
int Insert(INSERT_METHOD_ENUM eMothed, BIGINT_STRU *pBigInt, unsigned short usData);
int Multiply(BIGINT_STRU *pBigInt, unsigned short usMultiplier);
void DeleteZeroNode(BIGINT_STRU *pBigInt);
int Div(const BIGINT_STRU *pDividend,
const unsigned short usDividor,
BIGINT_STRU *pQuotient,
unsigned short *usRemainder
);
void Destroy(BIGINT_STRU *pBigInt);
void ToString(const BIGINT_STRU *pBigInt, char *pOut, unsigned int unLen);
void Reverse(char *pOut, unsigned int unLen);
int main(int argc, char *argv[])
{
BIGINT_STRU stBigInt;
unsigned short suIndex;
unsigned short suTestNum = 13;
char *buff = NULL;
if ( 0 != Init(&stBigInt) )
{
return 1;
}
for ( suIndex = 1 ; suIndex <= suTestNum; suIndex++ )
{
Multiply(&stBigInt, suIndex);
}
buff = (char *)malloc((MAX_LEN + 1) * sizeof(char));
if(NULL == buff)
{
return 1;
}
ToString(&stBigInt, buff, MAX_LEN);
printf("%s\n", buff);
free(buff);
Destroy(&stBigInt);
return 0;
}
int Init(BIGINT_STRU *pBigInt)
{
BIGINT_NODE_STRU *pNode = NULL;
if ( NULL == pBigInt )
{
return 1;
}
pNode = (BIGINT_NODE_STRU *)malloc(sizeof(BIGINT_NODE_STRU));
if ( NULL == pNode)
{
return 1;
}
pNode->usData = 0;
pNode->pNext = pNode;
pNode->pPre = pNode;
pBigInt->pHead = pNode;
return 0;
}
int Insert(INSERT_METHOD_ENUM eMothed, BIGINT_STRU *pBigInt, unsigned short usData)
{
BIGINT_NODE_STRU *pNode = NULL;
if ( NULL == pBigInt )
{
return 1;
}
pNode = (BIGINT_NODE_STRU *)malloc(sizeof(BIGINT_NODE_STRU));
if ( NULL == pNode)
{
return 1;
}
pNode->usData = usData;
if ( NEXT == eMothed)
{
pNode->pNext = pBigInt->pHead->pNext;
pNode->pPre = pBigInt->pHead;
pBigInt->pHead->pNext->pPre= pNode;
pBigInt->pHead->pNext = pNode;
}
else if ( PRE == eMothed)
{
pNode->pNext = pBigInt->pHead;
pNode->pPre = pBigInt->pHead->pPre;
pBigInt->pHead->pPre->pNext= pNode;
pBigInt->pHead->pPre = pNode;
}
return 0;
}
int Multiply(BIGINT_STRU *pBigInt, unsigned short usMultiplier)
{
BIGINT_NODE_STRU *pPos = NULL;
unsigned int unResult = 0;
unsigned short usLow = 0;
unsigned short usHigh = 0;
if(NULL == pBigInt)
{
return 1;
}
if(pBigInt->pHead->pPre == pBigInt->pHead)
{
Insert(NEXT, pBigInt, usMultiplier);
return 0;
}
pPos = pBigInt->pHead->pPre;
while(pPos != pBigInt->pHead)
{
unResult = pPos->usData * usMultiplier + usHigh;
usLow = (unsigned short)(0x0000ffff & unResult) ;
usHigh = (unsigned short)(0x0000ffff & (unResult >> 16));
pPos->usData = usLow;
pPos = pPos->pPre;
}
if(0 != Insert(NEXT, pBigInt, usHigh))
{
return 1;
}
DeleteZeroNode(pBigInt);
return 0;
}
void DeleteZeroNode(BIGINT_STRU *pBigInt)
{
BIGINT_NODE_STRU *pPos = NULL;
BIGINT_NODE_STRU *pTmp = NULL;
if(NULL == pBigInt)
{
return;
}
pPos = pBigInt->pHead->pNext;
while(pBigInt->pHead != pPos && 0 == pPos->usData)
{
pTmp = pPos;
pPos->pPre->pNext = pPos->pNext;
pPos->pNext->pPre = pPos->pPre;
pPos = pPos->pNext;
free(pTmp);
}
}
int Div(const BIGINT_STRU *pDividend,
const unsigned short usDividor,
BIGINT_STRU *pQuotient,
unsigned short *usRemainder
)
{
BIGINT_NODE_STRU *pPos = NULL;
unsigned int unUnite = 0;
unsigned short usQuotient = 0;
unsigned short usRemainder2 = 0;
if ( NULL == pDividend || NULL == pQuotient )
{
return 1;
}
if ( 0 == usDividor )
{
return 1;
}
pPos = pDividend->pHead->pNext;
while ( pDividend->pHead != pPos)
{
unUnite = usRemainder2;
unUnite = (unUnite << 16) + pPos->usData;
usQuotient = unUnite / usDividor;
usRemainder2 = unUnite % usDividor;
if(0 != Insert(PRE, pQuotient, usQuotient))
{
return 1;
}
pPos = pPos->pNext;
}
*usRemainder = usRemainder2;
DeleteZeroNode(pQuotient);
return 0;
}
void Destroy(BIGINT_STRU *pBigInt)
{
BIGINT_NODE_STRU *pPos = NULL;
BIGINT_NODE_STRU *pTmp = NULL;
if( NULL == pBigInt )
{
return;
}
pPos = pBigInt->pHead->pNext;
while(pBigInt->pHead != pPos)
{
pTmp = pPos;
pPos->pPre->pNext = pPos->pNext;
pPos->pNext->pPre = pPos->pPre;
pPos = pPos->pNext;
free(pTmp);
}
free(pBigInt->pHead);
}
void ToString(const BIGINT_STRU *pBigInt, char *pOut, unsigned int unLen)
{
unsigned short usRemainder = 0;
unsigned int unCount = 0;
BIGINT_STRU pQuotient;
if ( 0 != Init(&pQuotient) )
{
return;
}
Div(pBigInt, 10, &pQuotient, &usRemainder);
pOut[unCount++] = '0' + usRemainder;
while(pQuotient.pHead != pQuotient.pHead->pNext)
{
BIGINT_STRU pQuotient2;
if ( 0 != Init(&pQuotient2) )
{
return;
}
Div(&pQuotient, 10, &pQuotient2, &usRemainder);
Destroy(&pQuotient);
pQuotient.pHead = pQuotient2.pHead;
if(unLen == unCount)
{
Destroy(&pQuotient);
Reverse(pOut, unCount - 1);
pOut[unCount] = '\0';
return;
}
pOut[unCount++] = '0' + usRemainder;
}
Reverse(pOut, unCount - 1);
pOut[unCount] = '\0';
Destroy(&pQuotient);
}
void Reverse(char *pOut, unsigned int unLen)
{
unsigned int unStart = 0;
unsigned int unEnd = unLen;
char cTmp;
if(NULL == pOut)
{
return;
}
while(unStart < unEnd)
{
cTmp = pOut[unStart];
pOut[unStart] = pOut[unEnd];
pOut[unEnd] = cTmp;
unStart++;
unEnd--;
}
}