数値の平方根を計算する

test112.gif
ここでは平方根を計算したい数値を素因数分解し、素因数が2つ以上ある場合にルートの外に出す方法を利用した。

計算の過程で用いた素因数分解処理用のクラスと関数は「数値を素因数分解する」と同じものを利用している。

依存環境:ATL
#include "math.h"
#include "atlcoll.h"
#include "atlstr.h"



class	CElementInfo
{
public:
	long	_nElement;
	ULONG	_nCount;

	CElementInfo()
	{
		_nElement = 0;
		_nCount = 0;
	}

	CElementInfo(long nElement,ULONG nCount)
	{
		_nElement = nElement;
		_nCount = nCount;
	}

	CElementInfo&	operator++()
	{
		_nCount++;
		return	*this;
	}
	CElementInfo&	operator++(int)
	{
		_nCount++;
		return	*this;
	}

	CElementInfo&	operator--()
	{
		if(_nCount)
			_nCount--;
		return	*this;
	}
	CElementInfo&	operator--(int)
	{
		if(_nCount)
			_nCount--;
		return	*this;
	}
};



//
//	素因数分解
//
bool	Digest(long nData,CAtlArray<CElementInfo>* pacElements)
{
	long	nElement;
	ULONG	nCount;
	long	nLoopMax;

	if(pacElements == NULL)
		return	false;
	pacElements->RemoveAll();

	//負の数なら素因数として-1を与える
	if(nData < 0)
	{
		pacElements->Add(CElementInfo(-1,1));
		nData *= -1;
	}
	if(nData == 0 || nData == 1)
		return	true;

	nLoopMax = (long)sqrt((double)nData) + 1;
	for(nElement = 2; nElement <= nLoopMax; nElement += 2)
	{
		if(nElement == 4)	//2で素因数分解を1回行った後は3,5,7...2n+1で処理を
			nElement--;	//行なうように4のときに1を減算

		nCount = 0;
		while(1)
		{
			if(nData % nElement)
				break;

			nCount++;
			nData /= nElement;
		}
		if(nCount > 0)
			pacElements->Add(CElementInfo(nElement,nCount));
		if(nData == 1)
			break;
	}
	if(nData > 1)
		pacElements->Add(CElementInfo(nData,1));

	return	true;
}





//
//	平方根
//
//pacInnerElementsはルートの中側
//pacOuterElementsはルートの外側
//
bool	SquareRoot(long nData,CAtlArray<CElementInfo>* pacInnerElements,CAtlArray<CElementInfo>* pacOuterElements)
{
	bool	ret;
	CAtlArray<CElementInfo>	acDigest;

	if(pacInnerElements)
		pacInnerElements->RemoveAll();
	if(pacOuterElements)
		pacOuterElements->RemoveAll();
	if(pacInnerElements == NULL || pacOuterElements == NULL)
		return	false;

	if(nData == 0 || nData == 1 || nData == -1)
		return	true;

	//素因数分解
	ret = Digest(nData,&acDigest);
	if(ret == false)
		return	false;

	size_t	i;
	size_t	nSize;

	nSize = acDigest.GetCount();
	for(i = 0; i < nSize; i++)
	{
		if(acDigest[i]._nCount == 1)
			pacInnerElements->Add(CElementInfo(acDigest[i]._nElement,1));
		else if(acDigest[i]._nCount % 2 == 0)
			pacOuterElements->Add(CElementInfo(acDigest[i]._nElement,acDigest[i]._nCount / 2));
		else
		{
			if(acDigest[i]._nCount != 0)
			{
				pacInnerElements->Add(CElementInfo(acDigest[i]._nElement,1));
				pacOuterElements->Add(CElementInfo(acDigest[i]._nElement,acDigest[i]._nCount / 2));
			}
		}
	}

	return	true;
}



//
//	平方根
//
//pacInnerElementsはルートの中側
//pacOuterElementsはルートの外側
//
bool	SquareRoot(long nData,long* pnInner,long* pnOuter)
{
	bool	ret;
	CAtlArray<CElementInfo>	acInnerElements;
	CAtlArray<CElementInfo>	acOuterElements;

	if(pnInner)
		*pnInner = 0;
	if(pnOuter)
		*pnOuter = 0;
	if(pnInner == NULL || pnOuter == NULL)
		return	false;
	if(nData == 0)
		return	true;


	////////////////////////////////////
	//平方根の計算
	//
	ret = SquareRoot(nData,&acInnerElements,&acOuterElements);
	if(ret == false)
		return	false;


	////////////////////////////////////
	//結果値の計算
	//

	size_t	i;
	size_t	j;
	size_t	nSizeI;
	size_t	nSizeJ;

	*pnInner = 1;
	nSizeI = acInnerElements.GetCount();
	for(i = 0; i < nSizeI; i++)
	{
		nSizeJ = acInnerElements[i]._nCount;
		for(j = 0; j < nSizeJ; j++)
			*pnInner *= acInnerElements[i]._nElement;
	}

	*pnOuter = 1;
	nSizeI = acOuterElements.GetCount();
	for(i = 0; i < nSizeI; i++)
	{
		nSizeJ = acOuterElements[i]._nCount;
		for(j = 0; j < nSizeJ; j++)
			*pnOuter *= acOuterElements[i]._nElement;
	}

	return	true;
}






bool	Test()
{
	bool	ret;
	long	nData;
	long	nInner;
	long	nOuter;
	CAtlString	strBuff;
	CAtlString	strMessage;

	nData = 200;

	ret = SquareRoot(nData,&nInner,&nOuter);
	if(ret == false)
		return	false;

	strMessage.Format(_T("√%d = %d√%d"),nData,nOuter,nInner < 0 ? nInner*-1 : nInner);
	if(nInner < 0)
		strMessage += _T("i");

	::MessageBox(NULL,strMessage,_T("結果"),MB_OK);

	return	true;
}

プロジェクトファイルをダウンロード


カテゴリー「数学」 のエントリー