C语言将循环小数/有限小数转换为分数
文章目錄
- 數(shù)學(xué)基礎(chǔ)
- 編程思路
- 代碼
數(shù)學(xué)基礎(chǔ)
早在小學(xué)的時候我就對循環(huán)小數(shù)非常感興趣,加上初中和高中對循環(huán)小數(shù)可以說有一定基礎(chǔ)研究,因此想到寫一個將循環(huán)下小數(shù)轉(zhuǎn)換為分?jǐn)?shù)的程序,非常有意思,并且對初學(xué)者來說,它的輸入輸出格式的轉(zhuǎn)換也是一大難點。
首先必須明確一點,循環(huán)小數(shù)必定可以轉(zhuǎn)換為分?jǐn)?shù),原因在于循環(huán)小數(shù)總可以分解為不循環(huán)的有限部分+循環(huán)的無限部分。前者對應(yīng)一個分?jǐn)?shù),后者可以寫成一個收斂的等比數(shù)列的和,也必定是可以轉(zhuǎn)換為一個分?jǐn)?shù)的。例如0.234343434…,有限部分為0.2=1/5,無限部分為0.0343434…=0.034/(1-0.01)=34/990=17/495;0.2343434…=1/5+17/495=116/495。同理,0.879879879…=0.879/(1-0.001)=879/999。
所以任何一個循環(huán)小數(shù)都可以化為分?jǐn)?shù),并且通過上述兩個例子,我們也對如何轉(zhuǎn)換有了一個初步的了解。
編程思路
這幾步非常關(guān)鍵,牽涉到我們的分母到底應(yīng)該怎么寫,如果分母有差錯,那之后的化簡都是白搭。
代碼
#include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> struct Decimal{int num;int den; };//定義分?jǐn)?shù)結(jié)構(gòu)體 void simplify(int *num,int *den);//化簡一個分?jǐn)?shù)的分子和分母 int GCD(int a,int b);//求兩個數(shù)的最大公約數(shù) int main() {char str1[100],str2[100],int1[10];//存放兩個分?jǐn)?shù)的字符串,后續(xù)再處理 float f1; int integer,dec1,num,den;//integer是整個小數(shù)的整數(shù)部分,dec1是有限部分的小數(shù)部分(不含小數(shù)點的),num和den分別是最終結(jié)果分?jǐn)?shù)的分子和分母struct Decimal Dec,Cir;//小數(shù)部分對應(yīng)的分?jǐn)?shù)結(jié)構(gòu)體(有限部分+循環(huán)部分) printf("*******小數(shù)轉(zhuǎn)換為分?jǐn)?shù)的實驗*********\n");printf("請輸入一串小數(shù),如有循環(huán)節(jié),請和有限部分用空格隔開,如沒有循環(huán)節(jié),請用0代替。\n");printf("例如0.2 34代表0.234343434......,3.8753 0代表3.8753\n");//對輸入的一個簡單說明scanf("%s%s",str1,str2);//這里不能用%f掃入,否則將不知道小數(shù)長度 f1=atof(str1);//將輸入的字符轉(zhuǎn)換為浮點數(shù) integer=(int)f1;//取整數(shù)部分dec1=atoi(strstr(str1,".")+1);itoa(integer,int1,10);//integer轉(zhuǎn)為字符串,方便計算長度 Dec.num=dec1;//有限小數(shù)的小數(shù)部分(注意是整形的,指的是不含小數(shù)點的小數(shù)部分)Dec.den=pow(10,strlen(str1)-strlen(int1)-1);Cir.num=atoi(str2);Cir.den=pow(10,strlen(str2))-1;Cir.den*=pow(10,(int)(log10(dec1)+1));if(Cir.num==0){simplify(&Dec.num,&Dec.den);num=Dec.num+integer*Dec.den;den=Dec.den;simplify(&num,&den);if(integer!=0)printf("轉(zhuǎn)換為帶分?jǐn)?shù)的結(jié)果為:%d+%d/%d\n",integer,Dec.num,Dec.den);printf("轉(zhuǎn)換為分?jǐn)?shù)的結(jié)果為:%d/%d\n",num,den); return 0;} //如果循環(huán)小數(shù)是0,直接轉(zhuǎn)換有限部分即可,否則需要將循環(huán)部分加以轉(zhuǎn)換,并與有限部分的分?jǐn)?shù)相加 simplify(&Dec.num,&Dec.den);simplify(&Cir.num,&Cir.den);den=Dec.den*Cir.den;num=Dec.num*Cir.den+Dec.den*Cir.num;if(integer!=0)printf("轉(zhuǎn)換為帶分?jǐn)?shù)結(jié)果為:%d+%d/%d\n",integer,num,den);num+=den*integer;printf("轉(zhuǎn)換為分?jǐn)?shù)結(jié)果為:%d/%d\n",num,den); return 0; } int GCD(int a,int b) {//利用輾轉(zhuǎn)相除法求兩個數(shù)的最大公約數(shù) if(a==1||b==1)return 1;int t;if(a<b){t=a;a=b;b=t;}//保證a是大數(shù)while(b>0){t=b;//t臨時存放小數(shù)b=a%b;//小數(shù)是上一次兩個數(shù)相除的余數(shù)a=t;//大數(shù)是上一次相除的小數(shù)}return a; } void simplify(int *num,int *den) {int gcd=GCD(*num,*den);*num=*num/gcd;*den=*den/gcd; }那么好,我們來輸入一個循環(huán)小數(shù)進(jìn)行驗證,如果位數(shù)比較多的話,出來的應(yīng)該是個變態(tài)的答案,當(dāng)然你要相信自己是對的:
下面我們用Win10自帶的計算器驗證一下(科學(xué)模式)
說明我們的結(jié)果沒問題,大功告成。
總結(jié)
以上是生活随笔為你收集整理的C语言将循环小数/有限小数转换为分数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 腾讯笔试经验-不是大牛-勿看
- 下一篇: 赫夫曼编码树(图解+完整代码)