小数转换分数
小数转换成分数的时候,是让小数有更精确的表示。这个问题可以分两种情况来解决:有限小数和循环小数。
对于有限小数:
我们可以直接把后面的a作为分子,分母就是10^n,然后再约分。约分就是求分子和分母的最大公约数,然后除以它就可以了。最大公约数的问题我们可以通过辗转相除法来做(会面会讲到其他更加高效的方法求最大公约数)。
对于循环小数:
循环的部分用括号括起来的。
求分子和分母的数值,需要用个数学的方法。这部分编程之美上讲的比较清楚,如下:
代码如下,有几点需要注意的:
#include<iostream> #include<string> #include<math.h> using namespace std; // 求最大公约数函数 __int64 gcd(__int64 a, __int64 b) { __int64 m; for(m = a % b; m != 0; m = a % b) { a = b; b = m; } return b; } int main() { string input; while(cin>>input) { int indexDot = input.find('.') + 1; // 小数点的位置 int indexXH = input.find('('); // 循环位的位置 bool flag = false; if(indexXH != string::npos) { flag = true; // 说明有循环位 indexXH++; } // 有限小数转分数 if(!flag) { int lenDecimal = input.length() - indexDot; string decimal = input.substr(indexDot, lenDecimal); __int64 up = atoi(decimal.c_str()); // 得到分子 //cout<<lenDecimal<<' '<<up<<endl; __int64 down = pow(10, lenDecimal); __int64 common = gcd(up, down); printf("分子是:%I64d\t分母是:%I64d\n", up/common, down/common); } // 循环小数转分数 else { int n = indexXH - indexDot - 1; //非循环位的长度 int m = input.length() - indexXH - 1; // 循环位的长度 string strN = input.substr(indexDot, n); string strM = input.substr(indexXH, m); int num1 = atoi(strN.c_str()); int num2 = atoi(strM.c_str()); //cout<<num1<<' '<<num2<<' '<<m<<' '<<n<<endl; __int64 up = num1 * (pow(10, m) - 1) + num2; __int64 down = (pow(10, m) - 1) * pow(10, n); //printf("%I64d\t%I64d", up, down); __int64 common = gcd(up, down); printf("分子是:%I64d\t分母是:%I64d\n", up/common, down/common); } } return 0; }
参考:
http://baike.baidu.com/link?url=bKd5HZCm59WATWhZu6YVXzFqQZIN3yLovxVcja-rneHw7uzRDCXheB_aVdExiGDsxfgp7lw_c2LQMap3qGScV_
http://baike.baidu.com/link?url=bKd5HZCm59WATWhZu6YVXzFqQZIN3yLovxVcja-rneHw7uzRDCXheB_aVdExiGDsxfgp7lw_c2LQMap3qGScV_
https://msdn.microsoft.com/zh-tw/library/29dh1w7z.aspx