Skip to content

166. Fraction to Recurring Decimal

On LeetCode ->

Problem

Convert a fraction numerator / denominator into its decimal string.

  • If the decimal terminates, return it normally.
  • If digits repeat forever, wrap the repeating part in parentheses.
  • Keep the sign correct.

Example:

4 / 333 -> "0.(012)"

Key trick

Track each remainder's first position in the output.

  • In long division, the decimal starts repeating exactly when a remainder repeats.
  • When that happens, insert ( at the first position where that remainder appeared, and append ) at the end.

Trap

  • Forgetting sign handling when one value is negative.
  • Not returning just the integer part when remainder is 0.
  • Tracking digits instead of remainders.
  • Mishandling cases like -1 / -2, 0 / 5, or 1 / 6.

Why is it interesting?

It turns manual long division into code.

  • It tests hash map usage, edge cases, and careful string construction.
  • The repeating-cycle idea is simple but easy to miss.

Python solution

class Solution:
    def fractionToDecimal(self, numerator: int, denominator: int) -> str:
        a, b = numerator, denominator

        # Zero is a special case: no sign, no fractional part.
        if a == 0:
            return "0"

        parts = []

        if (a < 0) != (b < 0):
            parts.append("-")

        a = abs(a)
        b = abs(b)

        # Integer part.
        int_part, rem = divmod(a, b)
        parts.append(str(int_part))

        # No fractional part.
        if rem == 0:
            return "".join(parts)

        parts.append(".")

        # rem -> index in parts where its digit starts
        seen = {}

        while rem:
            # If this remainder was seen before, digits from that point repeat.
            if rem in seen:
                repeat_idx = seen[rem]
                parts.insert(repeat_idx, "(")
                parts.append(")")
                break

            # Record where the next digit produced by this remainder will go.
            seen[rem] = len(parts)

            rem *= 10
            digit, rem = divmod(rem, b)
            parts.append(str(digit))

        return "".join(parts)

Comment on my solution

Not provided.

Extra

Mathematical background to understand the algorithm

The code is clear but I've no clue why it works.

Why this:

Track each remainder's first position in the output.

  • In long division, the decimal starts repeating exactly when a remainder repeats.
  • Give me the necessary mathematical background to understand what's going on. Use mathematical notation.
  • And go through the algo for the following case:
  • (4, 333, "0.(012)")
  • (1, 6, "0.1(6)")
  • (50, 8, "6.25")

Think of the decimal part as long division driven only by the remainder.

For a fraction \(\dfrac{n}{d}\), after removing the integer part, let

\[ r_0 = n \bmod d \]

with \(0 \le r_0 < d\).

Each decimal digit is produced by this recurrence:

\[ 10r_k = d \cdot a_{k+1} + r_{k+1} \]

where:

  • \(a_{k+1}\) is the next decimal digit
  • \(r_{k+1}\) is the new remainder
  • equivalently,
\[ a_{k+1} = \left\lfloor \frac{10r_k}{d} \right\rfloor, \qquad r_{k+1} = (10r_k) \bmod d \]

So the whole fractional expansion is determined by repeatedly applying:

\[ r \mapsto (10r) \bmod d \]

and outputting the corresponding digit.

Why repeating a remainder means repeating digits

The key fact is:

  • if the same remainder appears again, everything after it repeats identically.

Why?

  • The next digit depends only on the current remainder.
  • The remainder after that also depends only on the current remainder.

So if \(r_i = r_j\) for some \(i < j\), then:

\[ a_{i+1} = a_{j+1}, \quad r_{i+1} = r_{j+1} \]

and then again:

\[ a_{i+2} = a_{j+2}, \quad r_{i+2} = r_{j+2} \]

and so on forever. Thus the block from position \(i+1\) to \(j\) repeats.

This is exactly why we store:

  • each remainder
  • the position in the output where its digit starts

When a remainder comes back, we know where the repeating block began.

Why a remainder must eventually repeat or become \(0\)

All remainders satisfy:

\[ 0 \le r < d \]

So there are only finitely many possible remainders:

\[ 0, 1, 2, \dots, d-1 \]

Therefore during long division:

  • either some remainder becomes \(0\), and the decimal terminates
  • or some nonzero remainder repeats, and the decimal becomes periodic

This is just the pigeonhole principle.

Why remainder \(0\) means terminating decimal

If at some step \(r_k = 0\), then

\[ 10r_k = 0 \]

so every future digit is \(0\), and long division stops. That means the decimal is finite.


Example 1: \(\dfrac{4}{333} = 0.(012)\)

Integer part:

\[ \left\lfloor \frac{4}{333} \right\rfloor = 0 \]

so start with:

0.

Initial remainder:

\[ r_0 = 4 \]

Now iterate.

Step 1
\[ 10r_0 = 40 \]
\[ a_1 = \left\lfloor \frac{40}{333} \right\rfloor = 0 \]
\[ r_1 = 40 \]

Output digit: 0

Current decimal:

0.0

Store that remainder 4 produced the digit at this position.

Step 2
\[ 10r_1 = 400 \]
\[ a_2 = \left\lfloor \frac{400}{333} \right\rfloor = 1 \]
\[ r_2 = 400 \bmod 333 = 67 \]

Output digit: 1

Current decimal:

0.01
Step 3
\[ 10r_2 = 670 \]
\[ a_3 = \left\lfloor \frac{670}{333} \right\rfloor = 2 \]
\[ r_3 = 670 \bmod 333 = 4 \]

Output digit: 2

Current decimal:

0.012

Now the new remainder is again:

\[ r_3 = 4 = r_0 \]

So we are back to exactly the same state as at the start. Therefore the same digits will repeat:

  • from remainder \(4\) we got digit 0
  • then remainder \(40\) gave 1
  • then remainder \(67\) gave 2
  • then back to remainder \(4\)

So the repeating block is 012:

0.(012)

A compact state table:

\[ 4 \to (0,40) \to (1,67) \to (2,4) \to \cdots \]

Example 2: \(\dfrac{1}{6} = 0.1(6)\)

Integer part:

\[ \left\lfloor \frac{1}{6} \right\rfloor = 0 \]

Start:

0.

Initial remainder:

\[ r_0 = 1 \]
Step 1
\[ 10r_0 = 10 \]
\[ a_1 = \left\lfloor \frac{10}{6} \right\rfloor = 1 \]
\[ r_1 = 10 \bmod 6 = 4 \]

Output digit: 1

Current decimal:

0.1
Step 2
\[ 10r_1 = 40 \]
\[ a_2 = \left\lfloor \frac{40}{6} \right\rfloor = 6 \]
\[ r_2 = 40 \bmod 6 = 4 \]

Output digit: 6

Current decimal:

0.16

Now:

\[ r_2 = 4 = r_1 \]

So from this point we are in a loop. The repeating block starts where remainder 4 first appeared, which is just before digit 6.

Hence:

0.1(6)

State view:

\[ 1 \to (1,4) \to (6,4) \to (6,4) \to \cdots \]

So after the first digit 1, we keep repeating 6.


Example 3: \(\dfrac{50}{8} = 6.25\)

Integer part:

\[ \left\lfloor \frac{50}{8} \right\rfloor = 6 \]

Remainder:

\[ r_0 = 50 \bmod 8 = 2 \]

Start:

6.
Step 1
\[ 10r_0 = 20 \]
\[ a_1 = \left\lfloor \frac{20}{8} \right\rfloor = 2 \]
\[ r_1 = 20 \bmod 8 = 4 \]

Output digit: 2

Current decimal:

6.2
Step 2
\[ 10r_1 = 40 \]
\[ a_2 = \left\lfloor \frac{40}{8} \right\rfloor = 5 \]
\[ r_2 = 40 \bmod 8 = 0 \]

Output digit: 5

Current decimal:

6.25

Now the remainder is \(0\), so division ends. No repetition.


How this maps to the code

Suppose during fractional-digit generation you have remainder r.

The code does this:

remainder *= 10
digit, remainder = divmod(remainder, denominator)

That is exactly:

\[ a = \left\lfloor \frac{10r}{d} \right\rfloor, \qquad r' = (10r) \bmod d \]

The dictionary:

seen[remainder] = position

means:

  • "if this remainder ever appears again, the repeating part starts at this output position"

That works because:

  • a remainder is the full state of the long division
  • same state implies same future
  • so same remainder implies repeating suffix

The whole idea is really just:

\[ \text{decimal expansion} = \text{deterministic process on finitely many remainders} \]

Finite deterministic process means:

  • hit \(0\) and stop
  • or enter a cycle

That cycle is the repeating decimal part.

Naming clarification

Just a naming clarification: Does "long division" has a rigourous definition or it is just a division?

"Long division" is usually the name of the standard written algorithm for division, not a different mathematical operation.

  • The operation is just division.
  • "Long division" means the step-by-step procedure used to compute:
    • the integer quotient
    • the remainder
    • and, if continued, the decimal expansion

So in this problem:

  • mathematically, you are computing \(\dfrac{n}{d}\)
  • algorithmically, you are simulating long division

It is not usually a fully rigorous formal term in math like "group" or "field".

It is more:

  • a standard school algorithm
  • a conventional name in arithmetic and education

In a more rigorous/algebraic description, you would say something like:

  • apply the division algorithm repeatedly
  • at each step compute quotient digit and remainder

using the fact that for integers \(a\) and \(d > 0\), there exist unique integers \(q, r\) such that

\[ a = dq + r \qquad\text{with}\qquad 0 \le r < d \]

That theorem is the rigorous backbone.

So short answer:

  • "division" is the math operation
  • "long division" is the usual manual algorithm for carrying it out digit by digit

I'm French. What is the French name for "Long division" algorithm?

The usual French name is:

  • la division posée

Sometimes you may also hear:

  • la division euclidienne posée for integer division with quotient and remainder
  • la technique de la division posée

For decimals, in school context, division posée is the natural translation of "long division".

So here the best translation is:

  • algorithme de la division posée

About the recurrence formula

  • How did you come up with this recurrence formula \(10r_k = d \cdot a_{k+1} + r_{k+1}\)? I don't get why this produce the decimal digit series.
  • How do you prove it?

Still not clear to me.

Let

\[ x=\frac{n}{d} \]

and suppose for simplicity that \(n,d>0\). The sign changes nothing.

The confusion usually comes from this point:

  • a decimal expansion is not magic
  • each next decimal digit is obtained by isolating the current fractional remainder, multiplying it by \(10\), and dividing again

I will build the formula from scratch.


Start from Euclidean division

First do the usual integer division:

\[ n = dq_0 + r_0 \qquad\text{with}\qquad 0 \le r_0 < d \]

So

\[ \frac{n}{d} = q_0 + \frac{r_0}{d} \]

Here:

  • \(q_0\) is the integer part
  • \(\dfrac{r_0}{d}\) is the fractional part left to expand

So the whole problem is now:

  • how do we write \(\dfrac{r_0}{d}\) in decimal?

Why multiply by \(10\)?

Because decimal digits are powers of \(10\).

If

\[ \frac{r_0}{d} = 0.a_1a_2a_3\cdots \]

then

\[ 10\cdot\frac{r_0}{d}=a_1+0.a_2a_3a_4\cdots \]

Multiplying by \(10\) shifts the decimal point one place to the right.

So the first digit after the decimal point is exactly the integer part of

\[ \frac{10r_0}{d} \]

That is why we divide \(10r_0\) by \(d\).


Deriving the recurrence

Now apply Euclidean division again, this time to \(10r_0\):

\[ 10r_0 = da_1 + r_1 \qquad\text{with}\qquad 0 \le r_1 < d \]

Divide by \(d\):

\[ \frac{10r_0}{d}=a_1+\frac{r_1}{d} \]

Then divide by \(10\):

\[ \frac{r_0}{d}=\frac{a_1}{10}+\frac{r_1}{10d} \]

This already says:

  • the first decimal digit is \(a_1\)
  • what remains afterward is controlled by \(r_1\)

Repeat the same step on \(10r_1\):

\[ 10r_1 = da_2 + r_2 \]

Then

\[ \frac{r_1}{d}=\frac{a_2}{10}+\frac{r_2}{10d} \]

Substitute into the previous expression:

\[ \frac{r_0}{d} = \frac{a_1}{10} + \frac{1}{10}\left(\frac{a_2}{10}+\frac{r_2}{10d}\right) = \frac{a_1}{10}+\frac{a_2}{10^2}+\frac{r_2}{10^2d} \]

Continue forever. After \(m\) steps:

\[ \frac{r_0}{d} = \sum_{i=1}^{m}\frac{a_i}{10^i} + \frac{r_m}{10^m d} \]

This formula is the rigorous reason the digits \(a_1,a_2,\dots\) are the decimal digits of \(\dfrac{r_0}{d}\).


The recurrence in general form

At step \(k\), divide \(10r_k\) by \(d\):

\[ 10r_k = d a_{k+1} + r_{k+1} \qquad\text{with}\qquad 0 \le r_{k+1} < d \]

This is just Euclidean division.

So automatically:

\[ a_{k+1} = \left\lfloor \frac{10r_k}{d} \right\rfloor \]

and

\[ r_{k+1} = (10r_k)\bmod d \]

That is where the recurrence comes from.

It is not invented. It is simply:

  • "take the current remainder"
  • "shift one decimal place"
  • "divide by \(d\) again"

Why does \(a_{k+1}\) have to be a decimal digit?

Because \(0 \le r_k < d\), so

\[ 0 \le \frac{10r_k}{d} < 10 \]

Hence

\[ 0 \le a_{k+1}=\left\lfloor \frac{10r_k}{d} \right\rfloor \le 9 \]

So each \(a_{k+1}\) is one of

\[ 0,1,2,\dots,9 \]

which is exactly a decimal digit.

This is important: the recurrence is not producing arbitrary integers. It really produces decimal digits.


Why this gives the decimal expansion

Suppose after the integer part \(q_0\), you generate digits \(a_1,a_2,\dots\) by the recurrence.

Then for every \(m \ge 1\):

\[ \frac{n}{d} = q_0+\sum_{i=1}^{m}\frac{a_i}{10^i} +\frac{r_m}{10^m d} \]

And since \(0 \le r_m < d\),

\[ 0 \le \frac{r_m}{10^m d} < \frac{1}{10^m} \]

So after taking the first \(m\) digits, the error is less than \(10^{-m}\).

That is exactly what it means for

\[ q_0.a_1a_2a_3\cdots \]

to be the decimal expansion of \(\dfrac{n}{d}\).

So this is the proof.


A concrete proof on \(\frac{1}{6}\)

Start with

\[ 1 = 6\cdot 0 + 1 \]

So

\[ \frac{1}{6}=0+\frac{1}{6} \]

Now divide \(10\cdot 1\) by \(6\):

\[ 10 = 6\cdot 1 + 4 \]

So

\[ \frac{10}{6}=1+\frac{4}{6} \]

Divide by \(10\):

\[ \frac{1}{6}=\frac{1}{10}+\frac{4}{60} \]

So the first decimal digit is \(1\).

Now divide \(10\cdot 4\) by \(6\):

\[ 40 = 6\cdot 6 + 4 \]

So

\[ \frac{40}{6}=6+\frac{4}{6} \]

Divide by \(10\):

\[ \frac{4}{6}=\frac{6}{10}+\frac{4}{60} \]

Substitute into the previous line:

\[ \frac{1}{6} = \frac{1}{10} + \frac{1}{10}\left(\frac{6}{10}+\frac{4}{60}\right) = \frac{1}{10}+\frac{6}{100}+\frac{4}{600} \]

Again, the same remainder \(4\) comes back, so the same digit \(6\) comes back forever.

Thus:

\[ \frac{1}{6}=0.1666\cdots \]

and written with repetition:

\[ \frac{1}{6}=0.1(6) \]

Intuition in one sentence

The remainder is "what is still left to convert into decimal", and multiplying it by \(10\) exposes the next decimal digit.


The shortest possible mental model

At any step, suppose the fraction still left is

\[ \frac{r_k}{d} \]

Then:

  1. Multiply by \(10\) to shift the next decimal digit into the integer part.
  2. Extract that integer part:
\[ a_{k+1}=\left\lfloor \frac{10r_k}{d}\right\rfloor \]
  1. Keep the new remainder:
\[ r_{k+1}=(10r_k)\bmod d \]

That leftover fraction is then

\[ \frac{r_{k+1}}{d} \]

waiting for the next digit.

So the process naturally repeats.