Click here to Skip to main content
15,892,746 members
Articles / Desktop Programming / MFC
Article

CFraction - a double / fraction / string conversion class

Rate me:
Please Sign up or sign in to vote.
4.83/5 (3 votes)
17 Apr 2000 118K   1.2K   37   15
A class that converts between doubles, strings and fractional representations.

Introduction

The CFraction class is a handy class when dealing with doubles and fractions. You can use it like a double and do anything you would do with a double, plus you assign strings to it. When you need to get a string representation, use one of the methods returning a CString. Or, if you do not use CString, there are methods for 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

The algorithm was developed using the formula for converting a decimal fraction to a string fraction. Any fractional part can be represented as:

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

where I1 is the integer part of the reciprocal of the fraction and I2 is the integer part of the reciprocal minus I1 ... etc. To determine the integer numerator and denominator, the expression can be reduced. It turns out that the numerator is simpler to calculate than the denominator, so the denominator can simply be determined by dividing the numerator by the original decimal.

Reduction of 1/(I1 + 1/(I2 + 1/(I3 + 1/In ... ))) - There is a way to mathematically reduce this elegantly. However, I think a simple step by step algebraic approach will be understood by more readers.

  • 1 I term: 1/I1 Numerator N1 = 1
  • 2 I terms: 1/(I1 + 1/I2) Multiply by I2/I2 = I2/((I1*I2) + 1),

    Numerator N2 = I2

  • 3 I terms: 1/(I1 + 1/(I2 + 1/I3)) Multiply by I3/I3 = 1/(I1 + I3/(I2*I3) + 1)

    then Multiply by ((I2*I3) + 1)/((I2*I3) + 1) = ((I2*I3) + 1)/(I1*((I2*I3) + 1) + I3),

    Numerator N3 = ((I2*I3) + 1)

  • 4 I terms: ...

    Multiply by I4/I4 = 1/(I1 + 1/(I2 + I4/(I3*I4) + 1))

    Multiply by (I3*I4) + 1) = 1/(I1 + ((I3*I4) + 1)/(I2*((I3*I4) + 1) + I4)).. ,

    Numerator N4 = I2*((I3*I4) + 1) + I4

As we continue, a pattern to the numerators appears showing that N1 = 1, N2 = I2, and Nn = In*Nn-2 + Nn-3 .

This is fairly simple to code.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionSmall error in formula? Pin
Philip Dam8-Dec-08 22:50
Philip Dam8-Dec-08 22:50 
AnswerRe: Small error in formula? Pin
Dean Wyant19-Dec-08 3:36
Dean Wyant19-Dec-08 3:36 
QuestionHi. i need some urgent help Pin
Mehran Gul22-Sep-08 5:14
Mehran Gul22-Sep-08 5:14 
AnswerRe: Hi. i need some urgent help Pin
Dean Wyant23-Sep-08 3:14
Dean Wyant23-Sep-08 3:14 
QuestionLicense Pin
janetec28-May-07 5:07
janetec28-May-07 5:07 
AnswerRe: License Pin
Dean Wyant29-May-07 2:36
Dean Wyant29-May-07 2:36 
QuestionHow do you install the class Pin
_matt_n00b_2-Nov-05 13:03
_matt_n00b_2-Nov-05 13:03 
AnswerRe: How do you install the class Pin
Dean Wyant3-Nov-05 5:16
Dean Wyant3-Nov-05 5:16 
Generalfractions Pin
brieanah10-Apr-03 19:00
sussbrieanah10-Apr-03 19:00 
GeneralRe: fractions Pin
Dean Wyant11-Apr-03 5:59
Dean Wyant11-Apr-03 5:59 
GeneralNegative Number Bug Pin
Dean Wyant16-Jan-02 8:39
Dean Wyant16-Jan-02 8:39 
GeneralRe: Negative Number Bug Pin
Dean Wyant17-Jan-02 7:20
Dean Wyant17-Jan-02 7:20 
GeneralThanks Pin
John1-Nov-00 9:48
John1-Nov-00 9:48 
Generalproject Pin
kirby20-Oct-00 8:43
kirby20-Oct-00 8:43 
GeneralRe: project Pin
Gene Zawadzki17-Apr-01 13:39
Gene Zawadzki17-Apr-01 13:39 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.