小數轉分數

   全部分數均可以表示成小數,可是小數中只有有限小數、無限循環小數能夠表示成分數,無限不循環小數不能表示成分數。函數

    有限小數改寫成分數:分子數小數部分的數,分母是10的分子長度的次冪;spa

    純循環小數改寫成分數:分子是一個循環節的數字組成的數,分母各位數字都是9,9的個數與循環節中的數字的個數相同;code

    混循環小數改寫成分數:分紅有限小數部分和循環節部分處理,各部分同上。rem

    最後找到分子、分母的最大公約數,把分數化成最簡分數便可。字符串

#include <stdio.h>
#include <string.h>


/* 函數功能:解析字符串爲分數
 * 參數表:strNum = 字符串,格式爲 *.*(*),括號內爲循環節
 *         intgr  = 整數部分
 *         nmrtr  = 分子
 *         dnmtr  = 分母
 * 返回值:0      = 輸入錯誤(括號未匹配)
 *         1      = 解析成功
 */

char fraction(char *strNum, int *intgr, unsigned *nmrtr, unsigned *dnmtr)
{
	char *pDot = strchr(strNum, '.');            // 小數點的位置
	char *pLeftBracket = strchr(strNum, '(');    // 左括號的位置
	char *pRightBracket = strchr(strNum, ')');   // 右括號的位置
	char *p;

	*intgr = 0;
	*nmrtr = 0;
	*dnmtr = 1;

	// 先處理整數部分
	p = (strNum[0] == '-' ? strNum + 1 : strNum);
	while((NULL != pDot && p < pDot) || (NULL == pDot && *p))
		*intgr = 10 * *intgr +  *p++ - '0';
	if(strNum[0] == '-')
		*intgr = -*intgr;


	// 再處理小數部分
	if(NULL == pDot)
		return 1;
	p = pDot + 1;
	// 沒有括號 = 有限小數:轉換成10的倍數做爲分母的分數
	if(NULL == pLeftBracket && NULL == pRightBracket)
	{
		while(*p)
		{
			*nmrtr = 10 * *nmrtr +  *p++ - '0';
			*dnmtr *= 10;
		}
	}
	// 有一對匹配的括號 = 無限循環小數
	else if(NULL != pLeftBracket && NULL != pRightBracket)
	{
		unsigned temp1 = 0, temp2 = 0, temp3 = 1, temp4 = 1;

		// 有限小數部分:同有限小數
		while(p < pLeftBracket)
		{
			temp1 = temp1 * 10 + *p++ - '0';
			temp3 *= 10;
		}
		// 循環節部分:分子爲一個循環節,分母爲循環節長度個數的 9
		p = pLeftBracket + 1;
		while(p < pRightBracket)
		{
			temp2 = temp2 * 10 + *p++ - '0';
			temp4 *= 10;
		}
		temp4--;
		// 合併:t1/t3 + t2/(t3*t4)
		*nmrtr = temp1 * temp4 + temp2;
		*dnmtr = temp3 * temp4;
	}
	// 只有一個括號 = 輸入錯誤
	else
	{
		return 0;
	}

	// 展轉相除法求分子、分母的最大公約數
	unsigned temp, gcd = *dnmtr, remainder = *nmrtr;
	while(remainder)
	{
		temp = gcd % remainder;
		gcd = remainder;
		remainder = temp;
	}
	*nmrtr /= gcd;
	*dnmtr /= gcd;

	return 1;
}


int main(int argc, char **argv)
{
	int intgr;
	unsigned nmrtr, dnmtr;

	if(argc == 2)
	{
		fraction(argv[1], &intgr, &nmrtr, &dnmtr);
		if(nmrtr > 0)
			printf("%s = %d %d/%d", argv[1], intgr, nmrtr, dnmtr);
		else
			printf("%s = %d", argv[1], intgr);
	}
	else
	{
		printf("Usage : %s *.*(*)", argv[0]);
	}

	return 0;
}
相關文章
相關標籤/搜索