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






4.83/5 (3投票s)
2000年4月18日

119369

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 。
这很容易编写代码实现。