码迷,mamicode.com
首页 > 其他好文 > 详细

【编程之美】精确表达浮点数

时间:2016-05-14 22:47:29      阅读:263      评论:0      收藏:0      [点我收藏+]

标签:

    在计算机中,使用float或double来存储小数是不能得到精确值的。如果你希望得到精确计算结果,最好是用分数形式来表示小数。有限小数或者无限循环小数都可以转化为分数。比如:

    0.9 = 9/10

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

    当然一个小数可以用好几种分数形式来表示。如:

    0.333(3) = 1/3 = 3/9

    给定一个有限小数或无限循环小数,你能否以分母最小的分数形式来返回这个小数呢?如果输入为循环小数,循环节用括号标记出来。下面是一些可能的输入数据,如0.3、0.30、0.3(000)、0.3333(3333)、……

分析与解法

(1) 有限小数情况

    如:X=0.a1a2...an

    可得10n*X=a1a2...an

    则X = a1a2...an/10n

(2) 从第一位开始循环的情况

    如Y=0.(b1b2...bm)

    则10m*Y=b1b2...bm.(b1b2...bm)=b1b2...bm+Y

    则Y=b1b2...bm/(10m-1)

(3) 则一般情况下的循环小数Z=0.a1a2...an(b1b2...bm)

    可知10n*Z=a1a2...an+Y=a1a2...an+b1b2...bm/(10m-1)

    Z=[(10m-1)a1a2...an+b1b2...bm]/[(10m-1)10n]

    最后进行约分即可得到结果。

    A/B = (A/(GCD(A, B)))/(B/(GCD(A, B)))

    参考代码如下:

技术分享
  1 #include <iostream>
  2 #include <string>
  3 #include <algorithm>
  4 using namespace std; 
  5 
  6 int gcd(int a, int b)
  7 {
  8     return (b == 0) ? a : gcd(b, a%b); 
  9 }
 10 
 11 int tenPow(int n)
 12 {
 13     int ret = 1; 
 14     for (int i = 0; i < n; i++)
 15     {
 16         ret *= 10; 
 17     }
 18     return ret; 
 19 }
 20 
 21 string intToString(int num)
 22 {
 23     string ret; 
 24     if (num == 0) num += 0; 
 25     while (num)
 26     {
 27         ret += num%10 + 0; 
 28         num /= 10; 
 29     }
 30     reverse(ret.begin(), ret.end()); 
 31     return ret; 
 32 }
 33 
 34 class Fraction
 35 {
 36 private:
 37     int intPart; // 整数部分
 38     int decPart; // 循环节前小数部分
 39     int cntDec;  // 循环节前小数部分的位数
 40     bool isCyc;  // 是否有循环节
 41     int cycPart; // 循环节部分
 42     int cntCyc;  // 循环节部分的位数
 43     
 44 public: 
 45     Fraction() // 默认构造函数
 46     {
 47         intPart = 0; 
 48         decPart = 0; 
 49         cntDec = 0; 
 50         isCyc = false; 
 51         cycPart = 0; 
 52         cntCyc = 0; 
 53     }
 54     
 55     Fraction(string str)
 56     {
 57         intPart = 0; 
 58         decPart = 0; 
 59         cntDec = 0; 
 60         isCyc = false; 
 61         cycPart = 0; 
 62         cntCyc = 0; 
 63         int i = 0, len = str.size(); 
 64         while (i < len && str[i] != .) // 计算整数部分
 65         {
 66             intPart = intPart * 10 + str[i] - 0; 
 67             i++; 
 68         }
 69         if (i < len) // 小数部分存在
 70         {
 71             i++; 
 72             while (i < len && str[i] != () // 计算循环体前小数部分
 73             {
 74                 decPart = decPart * 10 + str[i] - 0; 
 75                 i++; 
 76                 cntDec++; 
 77             }
 78             if (i < len) // 循环体存在
 79             {
 80                 i++; 
 81                 isCyc = true; 
 82                 while (i < len && str[i] != ))
 83                 {
 84                     cycPart = cycPart * 10 + str[i] - 0; 
 85                     i++; 
 86                     cntCyc++; 
 87                 }
 88             }
 89         }
 90     }
 91     
 92     string toString()
 93     {
 94         string ret; 
 95         int numerator = 0, denominator = 0; 
 96         if (isCyc) 
 97         {
 98             denominator = tenPow(cntDec) * (tenPow(cntCyc) - 1); 
 99             numerator = decPart * (tenPow(cntCyc) - 1) + cycPart; 
100         }
101         else 
102         {
103             denominator = tenPow(cntDec); 
104             numerator = decPart; 
105         }
106         int g = gcd(numerator, denominator); // 约分 
107         numerator /= g; 
108         denominator /= g; 
109         numerator += denominator * intPart; 
110         ret = intToString(numerator) + " / " + intToString(denominator); 
111         return ret; 
112     }
113 }; 
114 
115 int main(int argc, char *argv[])
116 {
117     string str; 
118     while (cin >> str)
119     {
120         Fraction fr(str); 
121         cout << fr.toString() << endl;  
122     }
123     return 0; 
124 }
View Code

【编程之美】精确表达浮点数

标签:

原文地址:http://www.cnblogs.com/xiaoxxmu/p/5493373.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!