fractions
decimal calculation
algorithms
computational mathematics
large numbers

Find the kth digit after the decimal point of a fraction a/b with a,b,k being very large integers less than 10e18

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

If a, b, and k can be extremely large, the naive long-division method is too slow because it needs k steps. For values near 10^18, an O(k) algorithm is not realistic.

The key observation is that the kth digit after the decimal point depends on a remainder that can be computed with modular arithmetic. Once you switch to modular exponentiation, the problem drops to O(log k).

The Core Formula

Let r = a mod b. The fractional digits of a / b depend only on r / b, because the integer part is irrelevant after the decimal point.

For the kth digit:

  1. Compute x = (r * 10^(k - 1)) mod b
  2. The answer is floor(10 * x / b)

That works because each decimal step in long division multiplies the current remainder by 10, extracts one digit, and keeps the next remainder modulo b.

So instead of simulating every digit from 1 through k, you jump directly to the remainder just before digit k.

A Fast Python Implementation

Python is a good fit here because its integers are arbitrary precision and pow supports modular exponentiation directly:

python
1def kth_digit(a: int, b: int, k: int) -> int:
2    if b == 0:
3        raise ZeroDivisionError("b must not be zero")
4    if k <= 0:
5        raise ValueError("k must be positive")
6
7    r = a % b
8    x = (r * pow(10, k - 1, b)) % b
9    return (10 * x) // b
10
11
12print(kth_digit(1, 7, 1))  # 1
13print(kth_digit(1, 7, 2))  # 4
14print(kth_digit(1, 7, 6))  # 8
15print(kth_digit(22, 7, 3)) # 2

For 1 / 7 = 0.142857..., the digits are:

  • first digit 1
  • second digit 4
  • sixth digit 7

The function reaches the target digit without materializing the earlier digits one by one.

Why pow(10, k - 1, b) Matters

The call pow(10, k - 1, b) computes 10^(k - 1) mod b efficiently using repeated squaring. That is the difference between a usable algorithm and an impossible one.

If you tried to compute 10^(k - 1) as a full integer first, the number would be enormous. If you tried to simulate long division up to k, the loop count would be enormous. Modular exponentiation avoids both problems.

That is the standard trick whenever you need to jump to a far-off position in a repeating decimal process.

Handling Special Cases

A few edge cases are worth checking:

  • If a % b == 0, then the fraction has no fractional part and every decimal digit is 0.
  • If b has only factors 2 and 5, the decimal terminates. After the terminating point, all later digits are 0.
  • If a is larger than b, that does not matter. The method begins with a % b, so the integer part is automatically ignored.

Here is a quick demonstration:

python
print(kth_digit(8, 4, 1))   # 0 because 8 / 4 = 2.0
print(kth_digit(3, 8, 1))   # 3 because 3 / 8 = 0.375
print(kth_digit(3, 8, 4))   # 0 after the decimal expansion ends

Complexity

The algorithm is efficient because:

  • modulo reduction is constant-time relative to the formula structure
  • modular exponentiation is O(log k)
  • only a fixed number of integer variables are stored

That is a huge improvement over the direct long-division approach, which is O(k).

For massive k, that complexity improvement is the whole point of the method.

Common Pitfalls

  • Simulating all digits one by one, which is too slow for very large k.
  • Forgetting to reduce a modulo b before working on the fractional part.
  • Using floating point arithmetic, which loses precision and breaks completely for large inputs.
  • Computing 10^(k - 1) as a full integer instead of using modular exponentiation.
  • Off-by-one errors between the first digit after the decimal point and zero-based indexing.

Summary

  • The kth digit after the decimal point can be computed directly with modular arithmetic.
  • Start with r = a mod b, because only the remainder affects the fractional digits.
  • Use pow(10, k - 1, b) to jump to the relevant remainder in O(log k) time.
  • The answer is floor(10 * x / b) after the modular step.
  • Avoid floating point and naive long division for large inputs.

Course illustration
Course illustration

All Rights Reserved.