5

I'm making some tests with float type (floating point number) with programming and in some of my tests I need to extract the fraction that originates the float value.

Let $ x $ be a floating point number, and $ a, b \in \mathbb{Z} $, where $ x \approxeq \frac{a}{b} $, I want to discover $ a $ and $ b $.

e.g., if I have $ 0.5 $, I need a method (maybe numerical?) that gives me $ \frac{1}{2} $ or some of its multiples.

If there's more than one method, I would like the fastest or simples to implement with a programming languagg.

Talysson
  • 153
  • What methods will you actually have access to, and what kinds of floating point numbers are you likely to encounter? 0.5 is one thing, but, for example, would you want to resolve 0.666666667 as $2/3$? Would you want 0.142857142 to show as $1/7$? It's relatively easy to convert those into fractions (as the answers below show), but interpreting them as what they're intended to be would be more difficult. – mardat Dec 03 '14 at 10:10
  • @mardat I'm using a C++ float type (it can also be a double type if needed), float has single precision and double has double precision (info here). I have access to common math C++ lib, but can also use GCD, LCM and other math functions that are not too slow to run that I could implement. I just want to convert them into fractions, not interpret them like that. – Talysson Dec 03 '14 at 12:41

4 Answers4

4

My favorite method would be continued fractions.

If the fraction is exact the process will (should! ;-)) converge :
(illustrations using the free pari/gp)

contfrac(0.14285) = [0, 7, 2857]

with the exact answer : $0+\dfrac 1{7+\dfrac 1{2857}}=\dfrac{2857}{20000}$

else you'll get a large integer after some terms (the difficult part is to decide when the number becomes large!) and should just ignore it (and the next terms) :

contfrac(0.142857142) = [0, 7, 23809523, 1, 2]

so that the answer will be nearly $\;0+\dfrac 17$

  • As you say, the difficult part is deciding when to stop – Henry Dec 03 '14 at 10:57
  • E.g. try something like $\sqrt{5}/2 \approx 0.6180339887$ where a "good" fraction will be the ratio of consecutive Fibonacci numbers, the bigger the better – Henry Dec 03 '14 at 11:11
  • Yes @Henry but note that we may elaborate the fraction as we obtain new terms and should stop anyway if the sum of the number of digits of numerator and denominator is nearly as long as the precision used (further a very large number should make us over-cross this threshold of 'digitsprecision minus 1'). – Raymond Manzoni Dec 03 '14 at 11:13
  • (in my second example using the large term I would obtain $\dfrac{23809523}{166666662}$ with an input of only $9$ digits). – Raymond Manzoni Dec 03 '14 at 11:19
  • There's some way to decide when to stop? Also, I tested it and saw that it can overflow the C++ float type sometimes. – Talysson Dec 03 '14 at 12:44
  • @Talysson: I proposed (in my comments) to stop just before the sum of number of digits of numerator and number of digits of denominator became larger than your 'working precision' (say $#n+#d<7$ digits for float and $#n+#d<17$ for double precision) (you may too multiply $n\times d$ and verify that it is smaller than $10^7$). To avoid overflow don't compute the inverse of remainders smaller than precision (say $10^{-6}$ and $10^{-16}$). Excellent continuation anyway! – Raymond Manzoni Dec 03 '14 at 13:10
  • @RaymondManzoni Oh, I guess that browser's cache didn't let me see this answer, but I see it now, I'm going to try it. Thanks! – Talysson Dec 03 '14 at 13:19
  • You are welcome @Talysson, excellent implementation! – Raymond Manzoni Dec 03 '14 at 13:21
1

Let $P=10^n$ where $10^{-n}$ denotes the precision of the floating point number. Compute the greatest common divisor of $G=Gcd(P\cdot F,P)$, where $F$ is the floating point number.

Then the answer is $\displaystyle\frac{F/G}{P/G}$.

Lehs
  • 14,252
  • 4
  • 28
  • 82
0

If you are given $0.5$, you are really given $0.5000000000000$. You can find what fraction this is simply by writing the fraction

$$\frac{5000000000000}{10000000000000} = \frac{5}{10} = \frac12$$

5xum
  • 126,227
  • 6
  • 135
  • 211
0

If your decimal is terminating, you only have to take it's number as the numerator and the respective power as the denominator. If it is recurring, but 1 complete set of recurring digits is given, there is a simple method given here. Your program may have to identify the no. of digits being repeated first. If even 1 complete set of recurring digits is not given, you can assume it to be terminating and give an approximate fraction (equal to the visible digits of the decimal).