//test.h
#ifndef _TEST_H
#define _TEST_H
#include <stdlib.h>
#define MAXSIZE 50
struct DoubleList
{
int sqlist[MAXSIZE];
int key;
int size;
int data;
} DLIST_S;
typedef struct Node
{
int data;
struct Node *plast;
struct Node *pnext;
} DNODE_S;
#if 1 /* 双链表相关操作 */
/*****************************************************************************
Description : 遍历打印链表的所有节点
Input Param :
Output Param : 无
Return Value :
*****************************************************************************/
void PrintNode(DNODE_S **ppLinkList);
/*****************************************************************************
Description : 创建双链表,并把第一个节点的数值初始化为data
Input Param :
Output Param : 无
Return Value : 成功返回0,失败返回-1
*****************************************************************************/
int CreateDoubleLinkList(DNODE_S **ppLinkList, int data);
/*获取链表中节点个数*/
/*****************************************************************************
Description : 获取链表中节点个数
Input Param :
Output Param : 无
Return Value : 返回节点个数
*****************************************************************************/
int GetListLength(DNODE_S **ppLinkList);
/*****************************************************************************
Description : 初始化一个新结点
Input Param :
Output Param : 无
Return Value :
*****************************************************************************/
void InitNewNode(DNODE_S **ppNewNode, int data);
/*****************************************************************************
Description : 获取链表中的最后一个节点
Input Param :
Output Param : 无
Return Value :
*****************************************************************************/
void GetLastNode(DNODE_S **ppLinkList, DNODE_S **pLastNode);
/*****************************************************************************
Description : 在链表第pos个位置插入数据等于data的节点
Input Param :
Output Param : 无
Return Value :
*****************************************************************************/
void InsertNode(DNODE_S **ppLinkList, int pos, int data);
/*****************************************************************************
Description : 删除链表中第pos个节点
Input Param :
Output Param : 无
Return Value :
*****************************************************************************/
void MoveNode(DNODE_S **ppLinkList, int pos);
#endif
#if 1 /* 数组和链表转换 */
/*****************************************************************************
Description : 将数组写入链表中,链表中的数据的先后顺序和数组中的顺序要保持一致
Input Param :
Output Param : 无
Return Value :
*****************************************************************************/
void IntToList(DNODE_S **ppLinkList, int *paiArray, int size);
/*****************************************************************************
Description : 将链表写入数组中,数组中的数据的先后顺序和链表中的顺序要保持一致
Input Param :
Output Param : 无
Return Value :
*****************************************************************************/
void ListToInt(DNODE_S *pLinkList, int *paiArray);
/*****************************************************************************
Description : 将字符数组写入链表中,链表中的数据的先后顺序和数组中的顺序要保持一致
Input Param :
Output Param : 无
Return Value :
*****************************************************************************/
void StringToList(DNODE_S **ppLinkList, const char *pcString);
/*****************************************************************************
Description : 将链表写入字符数组中,数组中的数据的先后顺序和链表中的顺序要保持一致
Input Param :
Output Param : 无
Return Value :
*****************************************************************************/
void ListToString(DNODE_S *pLinkList, char *pcString);
#endif
#if 1
/*****************************************************************************
Description : 获取小数的位数,如果是整数返回0
Input Param :
Output Param : 无
Return Value :
*****************************************************************************/
int GetDecimalLength(const char *pcNum);
/*****************************************************************************
Description : 判断字符是否为合法数字
Input Param :
Output Param : 无
Return Value :
*****************************************************************************/
bool IsValidNum(char c);
#endif
#endif
//test.cpp
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <string>
#include "test.h"
using namespace std;
#define ERR -1
#define OK 0
#define TEST 1
#define POSITIVE_NUMBER 0
#define NEGATIVE_NUMBER 1
#if 1
void PrintNode(DNODE_S **ppLinkList)
{
DNODE_S *node = *ppLinkList;
printf("\r\n");
printf("%d ", node->data);
while (node->pnext != NULL)
{
node = node->pnext;
printf("%d ", node->data);
}
}
int CreateDoubleLinkList(DNODE_S **ppLinkList, int data)
{
DNODE_S *pHeadNode;
pHeadNode = (DNODE_S *)malloc(sizeof(DNODE_S));
if (NULL == pHeadNode)
{
return ERR;
}
pHeadNode->data = data;
pHeadNode->plast = NULL;
pHeadNode->pnext = NULL;
*ppLinkList = pHeadNode;
return OK;
}
int GetListLength(DNODE_S **ppLinkList)
{
int count = 1;
DNODE_S *node = *ppLinkList;
if (NULL == node)
{
return 0;
}
while (node->pnext != NULL)
{
node = node->pnext;
count++;
}
return count;
}
void GetLastNode(DNODE_S **ppLinkList, DNODE_S **pLastNode)
{
DNODE_S *pTmpNode = *ppLinkList;
*pLastNode = NULL;
while (pTmpNode->pnext != NULL)
{
pTmpNode = pTmpNode->pnext;
}
*pLastNode = pTmpNode;
}
void InitNewNode(DNODE_S **ppNewNode, int data)
{
DNODE_S *pNewNode = NULL;
/* 初始化新结点 */
pNewNode = (DNODE_S *)malloc(sizeof(DNODE_S));
if (NULL == pNewNode)
{
return;
}
pNewNode->data = data;
pNewNode->plast = NULL;
pNewNode->pnext = NULL;
*ppNewNode = pNewNode;
}
void InsertNode(DNODE_S **ppLinkList, int pos, int data)
{
int index = 1;
int iNodeNum = GetListLength(ppLinkList);
DNODE_S *pPrevNode = *ppLinkList;
DNODE_S *pNextNode = NULL;
DNODE_S *pNewNode = NULL;
if (pos > iNodeNum || pos < 0)
{
return;
}
/* 初始化新结点 */
InitNewNode(&pNewNode, data);
/* 1、插入头部 */
if (0 == pos)
{
pPrevNode->plast = pNewNode;
pNewNode->pnext = pPrevNode;
*ppLinkList = pNewNode;
return;
}
/* 找到插入位置 */
while (index != pos)
{
pPrevNode = pPrevNode->pnext;
index++;
}
pNextNode = pPrevNode->pnext;
/* 2、插入尾部 */
if (iNodeNum == pos)
{
pPrevNode->pnext = pNewNode;
pNewNode->plast = pPrevNode;
return;
}
/* 3、插入中间位置 */
pNewNode->pnext = pNextNode;
pNewNode->plast = pPrevNode;
pPrevNode->pnext = pNewNode;
pNextNode->plast = pNewNode;
}
void MoveNode(DNODE_S **ppLinkList, int pos)
{
DNODE_S *node = *ppLinkList;
DNODE_S *pPrevNode = NULL;
DNODE_S *pNextNode = NULL;
while(pos--)
{
node = node->pnext;
}
pPrevNode = node->plast;
pNextNode = node->pnext;
pPrevNode->pnext = pNextNode;
pNextNode->plast = pPrevNode;
free(node);
}
#endif
#if 1 /* 数组和链表转换 */
void IntToList(DNODE_S **ppLinkList, int *paiArray, int size)
{
int j = 0;
int data = 0;
DNODE_S *s = *ppLinkList;
s->data = *(paiArray + (size-1));
for(j = 2; j < (size+1); j++)
{
data = *(paiArray + (size-j));
InsertNode(ppLinkList, 0, data);
}
return;
}
void ListToInt(DNODE_S *pLinkList, int *paiArray)
{
int j = 0;
DNODE_S *s = pLinkList;
while(s != NULL)
{
*(paiArray + j) = s->data;
s = s->pnext;
j++;
}
return;
}
bool IsValidNum(char c)
{
if ('0' <= c && c <= '9')
{
return true;
}
return false;
}
void StringToList(DNODE_S **ppLinkList, const char *pcString)
{
int i = 0;
int j = 0;
int data = 0;
int len = (int)strlen(pcString);
DNODE_S *s = *ppLinkList;
s->data = pcString[0] - '0';
for(i = 1, j = 1; i < len; i++)
{
if (IsValidNum(pcString[i]))
{
data = pcString[i] - '0';
InsertNode(ppLinkList, j, data);
j++;
}
}
return;
}
void ListToString(DNODE_S *pLinkList, char *pcString)
{
int j = 0;
DNODE_S *s = pLinkList;
while(s != NULL)
{
*(pcString + j) = s->data + '0';
s = s->pnext;
j++;
}
return;
}
#endif
#if 1
int CompareNum(char *pcNumA, char *pcNumB)
{
int lenA = (int)strlen(pcNumA);
int lenB = (int)strlen(pcNumB);
if (lenA > lenB)
{
return 1;
}
else if (lenA < lenB)
{
return -1;
}
else
{
return strcmp(pcNumA, pcNumB);
}
}
int GetDecimalLength(const char *pcNum)
{
int i = 0;
int len = (int)strlen(pcNum);
while (pcNum[i] != '\0' && pcNum[i] != '.')
{
i++;
}
if (i == len)
{
return 0;
}
return len - i - 1;
}
char* EnlargeNum(const char *pcNum, int size)
{
int i = 0, j = 0, k = 0;
char pcTemp[1024] = {0};
int iDecimalLen = GetDecimalLength(pcNum);
char *pcResult = NULL;
if (iDecimalLen > size)
{
return NULL;
}
/* 如果是整数,则直接在末尾补上size个'0' */
if (0 == iDecimalLen)
{
memcpy(pcTemp, pcNum, strlen(pcNum));
memset(pcTemp + strlen(pcNum), '0', size);
pcResult = (char*) malloc (strlen(pcNum)+size+1);
memset(pcResult, 0, strlen(pcNum)+size+1);
memcpy(pcResult, pcTemp, strlen(pcTemp));
return pcResult;
}
/* 如果是小数, 先偏移小数点,如果不够,末尾补'0' */
while (pcNum[i] != '\0')
{
if (pcNum[i] == '.')
{
i++;
k = 0;
continue;
}
pcTemp[j] = pcNum[i];
i++;
j++;
k++;
}
memset(pcTemp + j, '0', size - k);
/* 如果数字以'0'开头,要去除 */
if(pcTemp[0] == '0')
{
pcResult = (char*) malloc (strlen(pcTemp));
memset(pcResult, 0, strlen(pcTemp));
memcpy(pcResult, pcTemp + 1, strlen(pcTemp)-1);
}
else
{
pcResult = (char*) malloc (strlen(pcTemp)+1);
memset(pcResult, 0, strlen(pcTemp)+1);
memcpy(pcResult, pcTemp, strlen(pcTemp));
}
return pcResult;
}
#endif
#if 1
void OperatePlus(int numA, int numB, int &result, int &carry)
{
result = numA + numB + carry;
carry = result / 10;
result = result % 10;
}
void ExceedPlusAlgorithm(DNODE_S **ppResult, DNODE_S *pLastNode, int carry)
{
int sum = 0;
while (pLastNode->plast != NULL)
{
pLastNode = pLastNode->plast;
OperatePlus(pLastNode->data, 0, sum, carry);
InsertNode(ppResult, 0, sum);
}
if (0 != carry)
{
InsertNode(ppResult, 0, carry);
}
return;
}
void BigIntegerPlus(DNODE_S **ppResult, DNODE_S **ppNumA, DNODE_S **ppNumB)
{
int sum = 0;
int carry = 0;
int iLenOfA = 0;
int iLenOfB = 0;
DNODE_S *pLastNodeOfA = NULL;
DNODE_S *pLastNodeOfB = NULL;
DNODE_S *pNewNode = NULL;
if (NULL == ppNumA || NULL == ppNumB)
{
return;
}
iLenOfA = GetListLength(ppNumA);
iLenOfB = GetListLength(ppNumB);
if (0 == iLenOfA)
{
ppResult = ppNumB;
return;
}
if (0 == iLenOfB)
{
ppResult = ppNumA;
return;
}
GetLastNode(ppNumA, &pLastNodeOfA);
GetLastNode(ppNumB, &pLastNodeOfB);
/* 1、从两个数组最末位开始向前扫描,把对应的位数相加,有进位则加入前一位中 */
OperatePlus(pLastNodeOfA->data, pLastNodeOfB->data, sum, carry);
CreateDoubleLinkList(ppResult, sum);
while (pLastNodeOfA->plast != NULL && pLastNodeOfB->plast != NULL)
{
pLastNodeOfA = pLastNodeOfA->plast;
pLastNodeOfB = pLastNodeOfB->plast;
OperatePlus(pLastNodeOfA->data, pLastNodeOfB->data, sum, carry);
InitNewNode(&pNewNode, sum);
InsertNode(ppResult, 0, sum);
}
/* 2、如果P/Q两个数组数字一样多,则判断是否有进位 */
if (pLastNodeOfA->plast == NULL && pLastNodeOfB->plast == NULL)
{
if (0 != carry)
{
InsertNode(ppResult, 0, carry);
}
return;
}
/* 3、把没有扫描完的数组里的数字全部加入plus数组 */
if (pLastNodeOfB->plast != NULL)
{
ExceedPlusAlgorithm(ppResult, pLastNodeOfB, carry);
return;
}
if (pLastNodeOfA->plast != NULL)
{
ExceedPlusAlgorithm(ppResult, pLastNodeOfA, carry);
return;
}
}
#endif
#if 1
void OperateSub(int numA, int numB, int &result, int &carry)
{
if (numA + carry >= numB)
{
result = numA + carry - numB ;
carry = 0;
}
else
{
result = numA + carry + 10 - numB ;
carry = -1;
}
}
void ExceedSubAlgorithm(DNODE_S **ppResult, DNODE_S *pLastNode, int carry)
{
int sum = 0;
while (pLastNode->plast != NULL)
{
pLastNode = pLastNode->plast;
OperateSub(pLastNode->data, 0, sum, carry);
InsertNode(ppResult, 0, sum);
}
if (0 != carry)
{
InsertNode(ppResult, 0, carry);
}
return;
}
void BigIntegerSub(DNODE_S **ppResult, DNODE_S **ppNumA, DNODE_S **ppNumB)
{
int sum = 0;
int carry = 0;
int iLenOfA = 0;
int iLenOfB = 0;
DNODE_S *pLastNodeOfA = NULL;
DNODE_S *pLastNodeOfB = NULL;
DNODE_S *pNewNode = NULL;
if (NULL == ppNumA || NULL == ppNumB)
{
return;
}
iLenOfA = GetListLength(ppNumA);
iLenOfB = GetListLength(ppNumB);
if (0 == iLenOfA)
{
ppResult = ppNumB;
return;
}
if (0 == iLenOfB)
{
ppResult = ppNumA;
return;
}
GetLastNode(ppNumA, &pLastNodeOfA);
GetLastNode(ppNumB, &pLastNodeOfB);
/* 1、从两个数组最末位开始向前扫描,把对应的位数相加,有进位则加入前一位中 */
OperateSub(pLastNodeOfA->data, pLastNodeOfB->data, sum, carry);
CreateDoubleLinkList(ppResult, sum);
while (pLastNodeOfA->plast != NULL && pLastNodeOfB->plast != NULL)
{
pLastNodeOfA = pLastNodeOfA->plast;
pLastNodeOfB = pLastNodeOfB->plast;
OperateSub(pLastNodeOfA->data, pLastNodeOfB->data, sum, carry);
InitNewNode(&pNewNode, sum);
InsertNode(ppResult, 0, sum);
}
/* 2、如果P/Q两个数组数字一样多,则判断是否有进位 */
if (pLastNodeOfA->plast == NULL && pLastNodeOfB->plast == NULL)
{
if (0 != carry)
{
InsertNode(ppResult, 0, carry);
}
return;
}
/* 3、把没有扫描完的数组里的数字全部加入plus数组 */
if (pLastNodeOfA->plast != NULL)
{
ExceedSubAlgorithm(ppResult, pLastNodeOfA, carry);
return;
}
return;
}
char* FromatOutpuString(DNODE_S *pstResult, int iMaxDecimal, int flag)
{
int i = 0;
int j = 0;
int size = 0;
char *pcResult = NULL;
char *pcResultCopy = NULL;
/* 分配内存,要考虑正负号、小数点和末尾'\0',所以分配大小为size+3 */
size = GetListLength(&pstResult);
pcResult = (char*)malloc(size+3);
memset(pcResult, 0, size+3);
pcResultCopy = (char*)malloc(size+3);
memset(pcResultCopy, 0, size+3);
ListToString(pstResult, pcResult);
/* 去除计算结果前面多余的0,如0345,改为345 */
while (pcResult[i] != '\0')
{
if (pcResult[i] != '0')
{
break;
}
i++;
size--;
}
memcpy(pcResultCopy, pcResult + i, strlen(pcResult)-i+1);
memset(pcResult, 0, size+3);
printf("\r\n 去除前面的0: pcResultCopy = %s", pcResultCopy);
i = 0;
j = 0;
/* 设置正负号 */
if (1 == flag)
{
pcResult[j++] = '-';
}
if (iMaxDecimal > 0)
{
/* 原操作数有小数,需要还原小数点 */
while (i < size - iMaxDecimal)
{
pcResult[j++] = pcResultCopy[i++];
}
memset(pcResult + j, '.', 1);
memcpy(pcResult + j + 1, pcResultCopy + i, iMaxDecimal);
}
else
{
/* 若没有小数,直接把结果拷贝给pcResult */
memcpy(pcResult + j, pcResultCopy, size);
}
printf("\r\n 尚未去除尾部的0: pcResultCopy = %s, iMaxDecimal = %d", pcResult
, iMaxDecimal);
/* 消除尾部的0 */
i = (int)strlen(pcResult) - 1;
while (i >= 0)
{
if (pcResult[i] == '0')
{
pcResult[i] = '\0';
}
else if (pcResult[i] == '.')
{
pcResult[i] = '\0';
break;
}
else
{
break;
}
i--;
}
return pcResult;
}
void BigNumSub(const char *pcMinuend, const char *pcSubtrahend, char **
ppcResult)
{
int i = 0;
int j = 0;
int flag = 0;
int compare = 0;
int iLenDecimalA = 0;
int iLenDecimalB = 0;
int iMaxDecimal = 0;
DNODE_S *pstNumA = NULL;
DNODE_S *pstNumB = NULL;
DNODE_S *pstResult = NULL;
char *pcTemp = NULL;
char *pcMinuendEnlarge = NULL;
char *pcSubtrahendEnlarge = NULL;
char *pcFinalResult = NULL;
/* 获取最长小数位数 */
iLenDecimalA = GetDecimalLength(pcMinuend);
iLenDecimalB = GetDecimalLength(pcSubtrahend);
iMaxDecimal = (iLenDecimalA > iLenDecimalB) ? iLenDecimalA : iLenDecimalB;
/* 按最长小数位数放大两个操作数 */
pcMinuendEnlarge = EnlargeNum(pcMinuend,iMaxDecimal);
pcSubtrahendEnlarge = EnlargeNum(pcSubtrahend, iMaxDecimal);
/* 比较数字大小 */
compare = CompareNum(pcMinuendEnlarge, pcSubtrahendEnlarge);
if (compare < 0) /* 被减数小于减数,则交换数字字符串,并把正负标志位置为1
*/
{
pcTemp = pcMinuendEnlarge;
pcMinuendEnlarge = pcSubtrahendEnlarge;
pcSubtrahendEnlarge = pcTemp;
flag = NEGATIVE_NUMBER;
}
if (compare == 0) /* 两数相等,则直接返回结果为0的字符串 */
{
pcFinalResult = (char*)malloc(2);
memset(pcFinalResult, 0, 2);
pcFinalResult[0] = '0';
*ppcResult = pcFinalResult;
return;
}
#if TEST
printf("\r\n ============== Change Num ==============");
printf("\r\n pcMinuendEnlarge = %s", pcMinuendEnlarge);
printf("\r\n pcSubtrahendEnlarge = %s", pcSubtrahendEnlarge);
#endif
/* 把放大后的两个整数字符串放入链表,然后逐位相减 */
CreateDoubleLinkList(&pstNumA, 0);
CreateDoubleLinkList(&pstNumB, 0);
CreateDoubleLinkList(&pstResult, 0);
StringToList(&pstNumA, pcMinuendEnlarge);
StringToList(&pstNumB, pcSubtrahendEnlarge);
BigIntegerSub(&pstResult, &pstNumA, &pstNumB);
/* 恢复小数点,并去除整数前的0和小数尾部的0 */
pcFinalResult = FromatOutpuString(pstResult, iMaxDecimal, flag);
*ppcResult = pcFinalResult;
free(pstNumA);
free(pstNumB);
free(pstResult);
}
#endif
/*****************************************************************************
Description : 两个任意长度的正数相减
Prototype : int Decrease(const char *pMinuend, const char *pSubtrahend,
char **ppResult)
Input Param : const char *pMinuend 被减数,以\0表示字符串结束
const char *pSubtrahend 减数,以\0表示字符串结束
Output : char **ppResult 减法结果,必须以\0表示字符串结束
Return Value : 成功返回0 失败返回-1
*****************************************************************************/
int Decrease(const char *pcMinuend, const char *pcSubtrahend, char **ppResult)
{
#if TEST
printf("\r\n ============== Origin Num ==============");
printf("\r\n pcMinuend = %s", pcMinuend);
printf("\r\n pcSubtrahend = %s", pcSubtrahend);
#endif
BigNumSub(pcMinuend, pcSubtrahend, ppResult);
printf("\r\n ppResult = %s", *ppResult);
return 0;
}
int main(void)
{
char str1[] = "999999";
char str2[] = "11111111111";
char *str3 = NULL;
Decrease(str1, str2, &str3);
return 0;
}
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有