用分数形式精确表达有理数和循环无理数

来源:互联网 发布:魔法纹章数据加载失败 编辑:程序博客网 时间:2024/05/01 13:47

学过计算机编程的就知道,在计算机中,浮点数是不可能用浮点数精确的表达的,如果你需要精确的表达这个小数,我们最好是用分数的形式来表示,而且有限小数或无限小数都是可以转化为分数的形式。比如下面的几个小数:

0.3333(3)  = 1/3的(其中括号中的数字是表示循环节)

0.3 = 3 / 10

0.25 = 1 / 4

0. 285714(285714) = 2 / 7

为了简化编程,在这里,我们假定输入的数据都是以0.开始的,没有负数。

(1)、对于有限小数的情况很好分析,我们只要得到小数的位数n,然后用这个小数除以10^n就能得到

比如小数形式为0.a1a2a3a4...an = a1a2a3a4....an  / 10^n然后化简为最简分式就能得到。

(2)、对于无限小数,情况要复杂许多,假定无限小数为  0.a1a2....an(b1b2....bm),我们做如下转换有

X = 0.a1a2....an(b1b2....bm)

X * 10^n=a1a2....an + 0. b1b2....bm

设Y = 0. b1b2....bm有

10^m * Y = b1b2....bm + 0.b1b2....bm

=b1b2....bm + Y

所以Y = b1b2....bm / (10^m - 1)带入上面得到

X = (a1a2....an + Y) / 10^n  = ((a1a2....an) * (10^m - 1) + (b1b2....bm)) / ((10^m - 1) * 10^n)

由此我们可以得到无限小数的精确表达式,下面就是代码实现:

[cpp] view plaincopyprint?
  1. #include <iostream>  
  2. #include <string>  
  3.   
  4. using namespace std;  
  5.   
  6. unsigned long long GCD(unsigned long long a, unsigned long long b);  
  7. /** 
  8. *    author: w397090770 
  9. *    Date: 2012.08.31 
  10. *    Email:wyphao.2007@163.com 
  11. *    仅用于学习交流,转载请注明这些标识。 
  12. **/  
  13. void floatPrecisionExpress(string numberStr){  
  14.     //寻找 (    
  15.     string::size_type start = 0;  
  16.     //寻找 )   
  17.     string::size_type end = 0;  
  18.     //标记是否找到 ( 符号   
  19.     bool isFind = false;  
  20.     //记录字符串的长度   
  21.     int len = 0;  
  22.     int m = 0, n = 0;  
  23.     //分子,分母   
  24.     unsigned long long molecular = 0, denominator = 1;  
  25.     int i = 0;  
  26.       
  27.     //  
  28.     unsigned long long gcd = 1;  
  29.     start = numberStr.find('(', 0);  
  30.     end =  numberStr.find(')', 0);  
  31.       
  32.     //只有找到 ( 和 ) 才是对的,要么都不找到,找到一个地情况下是错误的,直接返回  
  33.     //当然我这里假设了用户输入的是0.XXXX格式的字符串,也就是一定是以0.开头的,  
  34.     //不考虑以别的开始的   
  35.     if(start == string::npos && end == string::npos){  
  36.         isFind = false;   
  37.     }else if(start != string::npos && end != string::npos){  
  38.         isFind = true;   
  39.     }else{  
  40.         cerr << "Input Error!" << endl;  
  41.         return;  
  42.     }  
  43.       
  44.     //有限小数   
  45.     if(!isFind) {  
  46.         len =  numberStr.length();  
  47.         n = len - 2;    //2是除去 0.  
  48.           
  49.         //计算分子   
  50.         for(i = 2; i < len; i++){  
  51.             molecular = molecular * 10 +  numberStr[i] - '0';  
  52.         }  
  53.         //cout << molecular << endl;  
  54.           
  55.         //计算分母   
  56.         for(i = 0; i < n; i++){  
  57.             denominator *= 10;  
  58.         }  
  59.         //cout << molecular << "\n" << denominator << endl;  
  60.         //将分子、分母化简为最简式,得到两数的最大公约数   
  61.         gcd= GCD(molecular, denominator);  
  62.         cout << "浮点数" <<  numberStr << "的分数精确表示为: " << molecular / gcd << "/" << denominator / gcd << endl;      
  63.     }else{  
  64.         n = start - 2;  //2是除去 0.  
  65.         m = end - start - 1;  
  66.         //cout << n << "\t" << m << endl;  
  67.         unsigned long long temp1 = 0, temp2 = 0, temp3 = 1, temp4 = 1;  
  68.         for(i = 2; i < start; i++){  
  69.             temp1 = temp1 * 10 + numberStr[i] - '0';  
  70.         }  
  71.           
  72.         for(i = start + 1; i < end; i++){  
  73.             temp2 = temp2 * 10 + numberStr[i] - '0';  
  74.         }  
  75.           
  76.         //cout << temp1 << "\t" << temp2 << endl;  
  77.         for(i = 0; i < n; i++){  
  78.             temp3 *= 10;  
  79.         }  
  80.           
  81.         for(i = 0; i < m; i++){  
  82.             temp4 *= 10;  
  83.         }  
  84.           
  85.         //cout << temp1 << "\t" << temp2 << "\t" << temp3 << "\t" << temp4 << endl;  
  86.         molecular = temp1 * (temp4 - 1) + temp2;  
  87.         denominator = (temp4 - 1) * temp3;  
  88.         gcd= GCD(molecular, denominator);  
  89.         //cout << gcd << endl;  
  90.         cout << "浮点数" <<  numberStr << "的分数精确表示为: " << molecular / gcd << "/" << denominator / gcd << endl;  
  91.           
  92.     }   
  93. }  
  94.   
  95. unsigned long long GCD(unsigned long long a, unsigned long long b){  
  96.     if(a < b){  
  97.         return GCD(b, a);  
  98.     }  
  99.       
  100.     if(b == 0){  
  101.         return a;  
  102.     }else{  
  103.         if(a & 0x1){    //奇数   
  104.             if(b & 0x1){  
  105.                 return GCD(b, a - b);   
  106.             }else{  
  107.                 return GCD(a, b >> 1);  
  108.             }  
  109.         } else{  
  110.             if(b & 0x1){  
  111.                 return GCD(a >> 1, b);  
  112.             }else{  
  113.                 return GCD(a >> 1, b >> 1) << 1;  
  114.             }  
  115.         }  
  116.     }  
  117. }  
  118.   
  119. int main(){  
  120.     floatPrecisionExpress("0.285714(285714)");  
  121.     floatPrecisionExpress("0.33(3)");  
  122.     floatPrecisionExpress("0.25");  
  123.     floatPrecisionExpress("0.30");  
  124.     floatPrecisionExpress("0.3(000)");  
  125.     floatPrecisionExpress("0.3333(3333)");  
  126.     return 0;  
  127. }  
程序运行结果:
原创粉丝点击