Is there an algorithm for figuring out the following things?
- If the result of a division is a repeating decimal (in binary).
- If it repeats, at what digit (represented as a power of 2) does the repetition start?
- What digits repeat?
Some examples:
1/2 = 1/10 = 0.1 // 1 = false, 2 = N/A, 3 = N/A, 4 = N/A
1/3 = 1/11 = 0.010101... // 1 = true, 2 = -2, 3 = 10
2/3 = 10/11 = 0.101010... // 1 = true, 2 = -1, 3 = 10
4/3 = 100/11 = 1.010101... // 1 = true, 2 = 0, 3 = 10
1/5 = 1/101 = 0.001100110011... // 1 = true, 2 = -3, 3 = 1100
Is there a way to do this? Efficiency is a big concern. A description of the algorithm would be preferred over code, but I'll take what answer I can get.
It's also worth noting that the base isn't a big deal; I can convert the algorithm over to binary (or if it's in, say base 256 to use char
s for ease, I could just use that). I say this because if you're explaining it might be easier for you to explain in base 10 :).
I can give a hint - repeating decimals in base ten are all fraction with the denominator having at least one prime factors other than two and five. If the denominator contains no prime factors two or five, they can always be represented with a denominator of all nines. Then the nominator is the repeating part and the number of nines is the length of the repeating part.
If there are prime factors two or five in the denominator, the repeating part starts not at the first position.
But I cannot remember how to derive the non-repeating part and its length.
This seem to translate well to base two. Only fraction with a power of two denominator are non-repeating. This can be easily checked by asserting that only a single bit in the denominator is set.
All fraction with odd denominators should be repeating and the pattern and its length can be obtained by expressing the fraction with a denominator in the form
2^n-1
.As for base ten, I cannot tell how to handle denominators containing but not being a power of two - for example 12 =
3 * 2^2
.First of all, one of your examples is wrong. The repeating part of
1/5
is0011
rather than1100
, and it begins at the very beginning of the fractional part.A repeating decimal is something like:
a/b = c + d(2-n + 2-n-k + 2-n-2k + ...)
= c + 2-n * d / (1 - 2-k)
in which
n
andd
are what you want.For example,
could be represented by the formula with
a = 1, b = 10(dec), c = 0, d = 0.0011(bin), n = 1, k = 4;
(1 - 2-k) = 0.1111
Therefore,
1/10 = 0.1 * 0.0011/0.1111
. The key part of a repeating decimal representation is generated by dividing by(2n - 1)
or its any multiple of 2. So you can either find a way to express your denominator as such (like building constant tables), or do a big number division (which is relatively slow) and find the loop. There's no quick way to do this.You can do a long division, noting the remainders. The structure of the remainders will give you the structure of any rational decimal:
In general the distances will give you the amount of digits for each part.
You can see this algorithm coded in C++ in the method
decompose()
here.Try
228142/62265
, it has a period of 1776 digits!To find the repeating pattern, just keep track of the values you use along the line:
As you reach the same value as you had at the second bit, the process will just repeat from that point producing the same bit pattern over and over. You have the pattern "0011" repeating from the second bit (first after decimal separator).
If you want the pattern to start with a "1", you can just rotate it until it matches that condition:
Edit:
Example in C#:
Called with your examples it outputs:
Check out decimal expansion, and specifically about the period of a fraction.