65.9K
CodeProject 正在变化。 阅读更多。
Home

CFraction - 一个双精度浮点数/分数/字符串转换类

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.83/5 (3投票s)

2000年4月18日

viewsIcon

119369

downloadIcon

1213

一个在双精度浮点数、字符串和分数表示之间进行转换的类。

引言

CFraction 类在处理 double 类型和分数时非常有用。你可以像使用 double 类型一样使用它,并执行任何你对 double 类型进行的操作,此外你还可以将字符串赋值给它。当需要获取字符串表示时,可以使用返回 CString 的方法。或者,如果你不使用 CString,则有用于 char * 的方法。

Example usage

  CFraction F1,F2;
  double D;
  CString S;
 
  // Assignment
  F1 = 5.126;        // double
  F2 = "5.126";      // string
  F1 = "5 63/500";   // string with fraction

  D = F1;            // double = CFraction
  F2 = D;            // CFraction = double

  // Math
  F1 = F2 + D;       // Mix and match them
  F2 = F1/D;
  // any math operation you want

  // Comparison
  if ((F1 > D) || (F1 < F2))
    D = F2/F1;
                      
  F2 = 15.0135;      // 5 27/2000
  
  S = F2.ToString(); // Returns "5 27/2000" 

  // Another version of ToString limits 
  // the denominator to the passed maximum value.
  S = F2.ToString(64); 
  // Returns "15 1/64" because 64 was exceeded
  // with first estimate 1/74 

  // Or, if you are working with stock prices
  // and you only want to show fractions when
  // the deniminator is 2,4,8,16,32,64,128,or 256
  // or up to passed maximum denominator ( <= 256) 
  S = F2.ToStockString(); 
  // Returns "15.0135" because fraction is not a normal stock price  

  // Or, force the denominator to be a valid
  // stock price denominator up to passed Max. Den. 
  S = F2.ForceToStockString();   // Returns closest stock price "15 3/256"
  S = F2.ForceToStockString(64); // Returns closest stock price "15 1/64" 
  
  // If you are like me, you are wondering what it will do with PI :-)
  F1 = 3.1415926535897932384626433832795; 
  // From Calculator - well beyond doubles capability
  S = F1.ToString(); // Returns  "3 3612111/25510582"
  // The difference is about 5.79087e-16 
  
  // You can increase precision when you know
  // that a value has a very large denominator. 
  // A double passed to ToString specifies the allowed error to shoot for. 
  // Warning: Using a smaller allowed error
  // can cause invalid results for fractions that 
  // can be accurately converted using a larger
  // allowed error. Also, since __int64 is used,
  // a denomintor cannot exceed 18 or 19 digits.
  S = F1.ToString(10.0e-50); 
  // Pushing it way up returns "3 36853866/260280919" 
  // The difference to double precision
  // is 0 because doubles accuracy was reached. 
  // The actual difference is about 1.27274e-16. 
  
  // If you have access to a more accurate type (like Calculator does),
  // you can replace double in the code
  // to increase accuracy. You can also 
  // replace __int64 if you want a denominator >  18 digits.

  // Lets try a resonable maximum denominator fo PI, like 999
  S = F1.ToString(999); // returns "3 16/113"

  // The first three estimates this class gives
  // for PI are 3 1/7, 3 15/106, and 3 16/113

该算法是使用将十进制分数转换为字符串分数公式开发的。任何分数部分都可以表示为

1/(I1 + 1/(I2 + 1/(I3 + 1/In ...

其中 I1 是分数倒数的整数部分,I2 是倒数减去 I1 的整数部分...等等。为了确定整数分子和分母,可以对表达式进行简化。结果是,分子比分母更容易计算,因此可以通过将分子除以原始小数来简单地确定分母。

简化 1/(I1 + 1/(I2 + 1/(I3 + 1/In ... ))) - 有一种数学上优雅地简化此表达式的方法。但是,我认为一个简单的逐步代数方法更容易被更多的读者理解。

  • 1 项: 1/I1 分子 N1 = 1
  • 2 项: 1/(I1 + 1/I2) 乘以 I2/I2 = I2/((I1*I2) + 1),

    分子 N2 = I2

  • 3 项: 1/(I1 + 1/(I2 + 1/I3)) 乘以 I3/I3 = 1/(I1 + I3/(I2*I3) + 1)

    然后乘以 ((I2*I3) + 1)/((I2*I3) + 1) = ((I2*I3) + 1)/(I1*((I2*I3) + 1) + I3),

    分子 N3 = ((I2*I3) + 1)

  • 4 项: ...

    乘以 I4/I4 = 1/(I1 + 1/(I2 + I4/(I3*I4) + 1))

    乘以 (I3*I4) + 1) = 1/(I1 + ((I3*I4) + 1)/(I2*((I3*I4) + 1) + I4)).. ,

    分子 N4 = I2*((I3*I4) + 1) + I4

随着继续,分子的模式出现,表明 N1 = 1, N2 = I2, 并且 Nn = In*Nn-2 + Nn-3

这很容易编写代码实现。

CFraction - 一个双精度浮点数/分数/字符串转换类 - CodeProject - 代码之家
© . All rights reserved.