一.问题描述
二.问题分析及思路
小数化分数:
1.对于不循环小数,小数点后有i位,则分子为这i位数,分母为10的i次方,约分得到最简分数(除最大公约数)
2.对于只有循环的小数,分子为循环的部分(i位),分母为i个9,如0.(436)=436/999
3.对于混合型,分子为所有数字减去非循环部分(i位),如0.32(692307)的分子为32692307-32,分母为循环数字个9加非循环数字个0,0.32(692307)的分母为6个9,2个0,即99999900
原理是不循环部分保留,循环部分按等比数列求和,可以自己推算一下。
实现
1.去掉前两位0和.,如果接下来第一位为(,则按循环型处理,pow函数按位把字符转化为数字
2.使用find函数,如果不含‘(’,按不循环小数处理,pow函数按位把字符转化为数字
3.最后一种情况为混合型,需要记录不循环的数字个数s1,循环的数字个数s2,用flag判断是哪个部分,遇到‘(’,flag=1,开始记录循环部分,同时直接求所有数字构成的数,遍历完后,根据s1,s2减去不循环的数字,并计算分母
三.代码
#include<iostream>
#include<string.h>
#include<cmath>
using namespace std;
int gcd(int a,int b)
{
if(a%b==0) return b;
else return gcd(b,a%b);
}
string f(string a)
{
a.erase(0,2);
string res="";
int len=a.length();
if(a[0]=='(')
{
int x=0,y=0;
for(int i=1;i<len-1;i++) {x+=(a[i]-'0')*pow(10,len-i-2);y+=pow(10,len-i-2)*9;}
res+=to_string(x/gcd(x,y))+"/"+to_string(y/gcd(x,y));
return res;
}
else if(a.find('(')==string::npos)
{
int x=0,y=1;
for(int i=0;i<len;i++) {x+=(a[i]-'0')*pow(10,len-i-1);y*=10;}
res+=to_string(x/gcd(x,y))+"/"+to_string(y/gcd(x,y));
return res;
}
else
{
int x=0,y=0,s1=0,s2=0,flag=0;
for(int i=0;i<len-1;i++) //到len-1,不取)
{
if(a[i]!='('&&flag==0) {s1++;x+=(a[i]-'0')*pow(10,len-i-3);}
else if(a[i]=='(') flag=1;
else if(flag==1) {s2++;x+=(a[i]-'0')*pow(10,len-i-2);}
}
for(int i=0;i<s2;i++) y+=9*pow(10,s2-i-1);
for(int i=0;i<s1;i++) {x-=(a[i]-'0')*pow(10,s1-1-i);y*=10;}
res+=to_string(x/gcd(x,y))+"/"+to_string(y/gcd(x,y));
return res;
}
}
int main()
{
string x;
int t;
cin>>t;
for(int i=0;i<t;i++)
{
cin>>x;
cout<<f(x)<<endl;
}
return 1;
}
最近事情多时间有点紧,解题都是倾向无脑直接写,写的可能会有点不清楚。。。.这道题只要知道小数转分数的原理,对着下标把字符转成需要的数字计算就可以,具体的下标和数字转化最好还是自己写一下。