最近面试中老被问两个大数放一块相乘要怎么弄。以前没考虑过这些问题,周末花点时间把面试时说的思路实现出来,大意是把一个数字,比如1234567890按位分成几段后分别存在一个字符串里,然后按照做乘法的方法,分别取单个两个字符串去做运算,把值保存在字符串里。不知道这算不算要求的实现大数乘法。代码如下。
.h文件
#pragma once
#include <string>
#include <tchar.h>
typedef std::basic_string<TCHAR> NumberString;
class BigNumberHelp
{
public:
BigNumberHelp(void);
~BigNumberHelp(void);
public:
NumberString Multiply(const NumberString& str1, const NumberString& str2);
private:
void SplitStringToAray(const NumberString& str, unsigned int* &Buff, unsigned int& nSize);
void TryIncreaseBit(unsigned int* Buff, unsigned int nBuffSize, unsigned int nPos, unsigned int nNumber);//给容器某位加数,并进位
private:
unsigned int m_nBitSize; //每个数组中存放几位数字
unsigned int m_nBitMax; //每个数组中存放数字最大值+1
};
.cpp
#include "StdAfx.h"
#include "BigNumberHelp.h"
#include <math.h>
BigNumberHelp::BigNumberHelp(void)
{
TCHAR szBuff[100] = {0};
_ultot_s(UINT_MAX, szBuff, 100, 10);
m_nBitSize = _tcslen(szBuff) / 2 -1;
m_nBitMax = pow(10.0, (double)m_nBitSize);
//m_nBitSize = 2 ;
//m_nBitMax = pow(10.0, (double)m_nBitSize);
}
BigNumberHelp::~BigNumberHelp(void)
{
}
NumberString BigNumberHelp::Multiply(const NumberString& strA, const NumberString& strB)
{
unsigned int* pBuffA = NULL;
unsigned int nBuffSizeA = 0;
unsigned int* pBuffB = NULL;
unsigned int nBuffSizeB = 0;
SplitStringToAray(strA, pBuffA, nBuffSizeA);
SplitStringToAray(strB, pBuffB, nBuffSizeB);
unsigned int nRetSize =nBuffSizeA + nBuffSizeB + 1;
unsigned int* pResult = new unsigned int[nRetSize];
memset(pResult, 0, nRetSize*sizeof(unsigned int));
for (unsigned int n = 0; n < nBuffSizeB; n++)
{
for (unsigned int k = 0; k < nBuffSizeA; k++)
{
unsigned int nRet = pBuffA[k] * pBuffB[n];
TryIncreaseBit(pResult, nRetSize, n+k, nRet);
}
}
NumberString strRet;
TCHAR* szRet = new TCHAR[m_nBitSize+1];
memset(szRet, 0, (m_nBitSize+1)*sizeof(TCHAR));
TCHAR szFormat[10] = {0};
_sntprintf_s(szFormat, 10, 10, _T("%%0%dd"), m_nBitSize);
for (int i = nRetSize-1; i >= 0; --i)
{
_sntprintf_s(szRet, m_nBitSize+1, m_nBitSize, szFormat, pResult[i]);
strRet += szRet;
}
delete[] szRet;
NumberString::size_type nTrimPos = strRet.find_first_not_of(_T("0"));
if (nTrimPos != NumberString::npos)
{
strRet.erase(0, nTrimPos);
}
return strRet;
}
void BigNumberHelp::SplitStringToAray(const NumberString& str, unsigned int* &pBuff, unsigned int& nBuffSize)
{
if (str.empty())
return;
unsigned int nSize = str.size();
nBuffSize = ((nSize%m_nBitSize) != 0)?(nSize / m_nBitSize + 1):(nSize/m_nBitSize);
pBuff = new unsigned int[nBuffSize];
memset(pBuff, 0, nBuffSize*sizeof(unsigned int));
unsigned int nIndex = 0;
unsigned int nPos = nSize;
while (nPos >= m_nBitSize)
{
nPos -= m_nBitSize;
NumberString strTemp = str.substr(nPos, m_nBitSize);
unsigned int nTemp = _ttoi(strTemp.c_str());
pBuff[nIndex] = nTemp;
nIndex++;
}
if (nPos > 0)
{
NumberString strLast = str.substr(0, nPos);
unsigned int nLast = _ttoi(strLast.c_str());
pBuff[nIndex] = nLast;
}
}
void BigNumberHelp::TryIncreaseBit(unsigned int* Buff, unsigned int nBuffSize, unsigned int nPos, unsigned int nNumber)
{
if (nPos == nBuffSize)
return;
int nRet = Buff[nPos] + nNumber;
int nBuffAdd = 0;
if (nRet >= m_nBitMax)
{
int nNewNum = nRet / m_nBitMax;
nBuffAdd = nRet - nNewNum*m_nBitMax;
TryIncreaseBit(Buff, nBuffSize, nPos+1, nNewNum);
}
else
{
nBuffAdd = nRet;
}
Buff[nPos] = nBuffAdd;
}
测试:
BigNumberHelp help;
NumberString strA = _T("123456789987654321");
NumberString strB = _T("1234567891");
NumberString strRet = help.Multiply(strA, strB);