converting a repeating decimal to a fraction

so i was given a book exercise where we are give 3 decimal expansion values:
2.5R0

0.08R3

0.R142857

so the "R" is for repeated portion of the fraction, for example; 0.08R3 = 0.083333333333(to infinity)

the goal of the exercise is to take these decimal expansions and convert them to fractions to cout to the counsel:
2.5R0 = 5/2

0.08R3 = 1/12

0.R142857 = 1/7


I am finding this extremely difficult to do,i tried following repeating decimal to fraction steps online, but often your doing different things to different type of fractions, so coming up with a general algorithm is though.

There is also a lot of problems such as decimal precision with repeating fractions, and creating a function that i can use to multiply the fractions to get rid of decimal points: (like getting 2.5 to be 25, 0.083 to be 83, and 0.142857 to be 142857)
I also feel like there is defiantly an easy solution going above my head because i'm doing allot of complex things and work arounds to get this to work and most of these exercises aren't nearly as complex.

I'm going to show one of my attempts to get this to work, please forgive how the code looks and how the functions/ variables are named, I've been at this for days and started over many times.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <iostream>
#include <string>
#include <cmath>
using namespace std;

double before_R(string str)
{
	int result_pos = str.find("R");
	string result = str.substr(0, result_pos);
	string number = "0123456789";
	int tens = 1;
	double new_result = 0;
	for (int i = result.length(); 0 < i; i--)
	{
		for (int j = 0; j < 10; j++)
		{
			if (result.substr(i, 1) == number.substr(j, 1))
			{
				new_result = new_result + j * tens;
				tens = tens * 10;
			}
		}
	}
	return abs(new_result);
}
double after_R(string str)
{
	int result_pos = str.find("R");
	string result = str.substr(result_pos);
	string number = "0123456789";
	int tens = 1;
	double new_result = 0;
	for (int i = result.length(); 0 < i; i--)
	{
		for (int j = 0; j < 10; j++)
		{
			if (result.substr(i, 1) == number.substr(j, 1))
			{
				new_result = new_result + j * tens;
				tens = tens * 10;
			}
		}
	}
	return abs(new_result);
}
double top(string str)
{
	//return abs( (before_R(str) ) * 10 + (before_R(str) - after_R(str)));
	//return abs((before_R(str) * 10 + after_R(str)) - (before_R(str) )) ;
	double new_number = before_R(str) * 10 + after_R(str);
	double old_number = before_R(str);
	double result = new_number - old_number;
	return result;
}
double bottom(string str)
{
	int compare = after_R(str);
	string convert = to_string(compare);
	int exponent = convert.length();
	int result = pow(10, exponent);
	result = result - 1;
	if (result < top(str))
	{
		return result * 100;
	}
	return result;
}
int g_c_f(int number1, int number2)
{
	int test = 0;
	if (number1 > number2)
	{
		test = number1;
	}
	else
	{
		test = number2;
	}
	int i = test;
	while (true)
	{
		if ((number1 % i == 0) && (number2 % i == 0))
		{
			return i;
		}
		i--;
	}

}
void display_fraction(string str)
{
	if (after_R(str) == 0)
	{
	}
	else
	{
		int divd = top(str);
		int divr = bottom(str);
		int factor = g_c_f(divd, divr);
		//int factor = 1;
		cout << divd / factor << "/" << divr / factor;
	}
}
int main()
{
	display_fraction("2.5R0");
	cout << endl;
	display_fraction("0.08R3");
	cout << endl;
	display_fraction("0.R142857");
	//cout << convertTens("0.08R3") << endl;
}
Last edited on
ok ....
can you do it 'on paper' (use a freaking calculator, but what I mean is without any code) ?

some of these are easy with a calculator:
consider .142857142857142857142857
if you do the 1/x button on the calculator, it happily gives you 7, and its done: you found it.

so lets trying something interesting.
1.571428571428571
or in your notation
1.R571428

if you do the 1/x button there, you get .R63 so no free answer. I like to work with less than 1 values, so I am going to approach it using the .R63 instead as I try to solve it, though.

n/d = 1.5..
d/n = .63
n = 1.5.. *d
d = .63.. *n
so really, then, you need a whole number that when multiplied by .R63 gives you a whole number, or nearly (x.999999999999 is ok, or x.00000000000001 is ok)
which you can find by brute force, but maybe there is a better way??
using brute force I find that 11 * .636363... = 7.
what is 11/7 ? ...
is there a smart way to solve for that 11 besides brute force? I don't know.

are you looking for exact small fractions or what? You can also punch it out and reduce the fractions but it may not repeat past the precision of a double; that is, its correct in the range of double but not the original fraction and eventually the repeating may fail... is that OK? That is easier to solve, just reduce 6363636/10000000 type thing...
Last edited on
There is a basic method for doing this that children learn in school:
https://www.basic-mathematics.com/converting-repeating-decimals-to-fractions.html

Presumably he knows that.

Example: Let x = 0.08R3

1000x = 83.333...
 100x =  8.333...
=================
 900x = 75

So, x = 75 / 900 = 1 / 12


I was able to write this up in about 30 lines.
Last edited on
ok, so is this the issue? : creating a function that i can use to multiply the fractions to get rid of decimal points

you don't need to get exotic here.
how many digits repeat?
use that many zeros in a power of 10.
so with the above approach (should have googled before trying it cold... lol)
0.R63 again ..
2 digits repeat, so you need to shift it by 2, and by twice that, so 4. Adjust for leading digits if necessary by adding 1 for each, as in his example you need 10 and 100 for the 1 repeating digit, becomes 1000 and 100 for his .083 one.
so
6363.63...
0063.63...
-------------
6300
9900
or 63/99 reduces (divide by 9).

you can probably use string.find, locate the "R", and subtract the length of the string and the R position to get the # of repeated digits (check, I may be off by one, but the general approach). I think you are close on this already.
something like this?

1
2
3
4
5
6
	string s = "0.08R3";
	string s2 = "0.R142857";   
	auto r = s.length()-s.find("R")-1;
	auto r2 = s2.length()-s2.find("R")-1;
	cout << s << " has " << r << " repeating digits\n";
	cout << s2 << " has " << r2 << " repeating digits\n";
Last edited on
You do have more code than you'll need when you've tightened things up.

Focus on the repeated fraction part to start with, assuming the whole number part is 0 and the repetitions start immediately after the decimal point, like 0.R142857, 0.R27, 0.R3.

Once you've solved that case you should be able to extend if easily enough to handle the other cases.

Regards

Andy
Split your string (using stringstream and the 3-argument form of getline()) into

x = a.bRc

where a, b and c are strings holding just integers (b and/or c may be empty).

Then:
10m+nx = abc.ccc.... where m and n are the lengths of strings a and b respectively.
10mx = ab.ccc...
So
10m+nx-10mx = abc-ab (form the string concatenation, then convert to integers using stoi() or, more likely, stoull())
Hence,
x = (abc-ab)/(10m+n-10m)

Finally, cancel down with the HCF (aka GCD) algorithm.
Last edited on
Topic archived. No new replies allowed.