Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Python

Python: คำนวณอนุกรม n + nn + nnn + ... + n(m ครั้ง)

โจทย์: คำนวณผลรวมของอนุกรมที่ตัวเลข n ซ้ำกันตามลำดับ

S = n + nn + nnn + nnnn + ... (m terms)

Example: n=2, m=4
S = 2 + 22 + 222 + 2222 = 2468

วิธีที่ 1: String Concatenation (เข้าใจง่าย)

def sum_series_string(n, m):
    """คำนวณอนุกรมโดยใช้ String Concatenation"""
    str_n = str(n)
    total = 0
    current = ""
    
    for i in range(m):
        current += str_n
        total += int(current)
    
    return total

print(sum_series_string(2, 4))  # 2468
print(sum_series_string(3, 3))  # 3 + 33 + 333 = 369

วิธีที่ 2: Mathematical Formula (เร็วกว่า O(1))

อนุกรมนี้สามารถคำนวณได้โดยสูตรปิด:

n + nn + nnn + ... (m terms)

= n × (1 + 11 + 111 + ... m terms)

= n × Σ(10^i - 1)/9 for i=1 to m

= n/9 × (Σ10^i - m)

= n/9 × (10(10^m - 1)/9 - m)

def sum_series_formula(n, m):
    """คำนวณด้วย Mathematical Formula O(1)"""
    if m <= 0:
        return 0
    # n/9 * (10*(10^m - 1)/9 - m)
    return n * (10 * (10**m - 1) // 9 - m) // 9

# ทดสอบ
print(sum_series_formula(2, 4))  # 2468
print(sum_series_formula(3, 3))  # 369
print(sum_series_formula(5, 5))  # 5 + 55 + 555 + 5555 + 55555 = 61725

วิธีที่ 3: ใช้ Recursion

def sum_series_recursive(n, m, current=0, total=0):
    """Recursive Approach"""
    if m == 0:
        return total
    current = current * 10 + n
    return sum_series_recursive(n, m - 1, current, total + current)

print(sum_series_recursive(2, 4))  # 2468

วิธีที่ 4: Generator + Sum (Pythonic)

def sum_series_generator(n, m):
    """ใช้ Generator Expression"""
    str_n = str(n)
    return sum(int(str_n * (i + 1)) for i in range(m))

print(sum_series_generator(2, 4))  # 2468

การทดสอบและเปรียบเทียบ Performance

import timeit

n, m = 9, 10

methods = {
    "String Loop": "sum_series_string(9, 10)",
    "Formula": "sum_series_formula(9, 10)",
    "Recursive": "sum_series_recursive(9, 10)",
    "Generator": "sum_series_generator(9, 10)",
}

for name, code in methods.items():
    time = timeit.timeit(code, globals=globals(), number=10000)
    print(f"{name:15}: {time:.6f}s")

ผลลัพธ์ทั่วไป

String Loop     : 0.012000s
Formula         : 0.000005s  (เร็วที่สุด O(1))
Recursive       : 0.008000s
Generator       : 0.010000s

Edge Cases และ Validation

def sum_series_robust(n, m):
    """Robust Version with Validation"""
    # Validate Inputs
    if not isinstance(n, int) or not isinstance(m, int):
        raise TypeError("n and m must be integers")
    if n < 0 or n > 9:
        raise ValueError("n must be a single digit (0-9)")
    if m < 0:
        raise ValueError("m must be non-negative")
    if m == 0:
        return 0
    
    # Use Formula for Efficiency
    return n * (10 * (10**m - 1) // 9 - m) // 9

# Test Cases
test_cases = [
    (2, 4, 2468),
    (3, 3, 369),
    (5, 5, 61725),
    (1, 1, 1),
    (9, 1, 9),
    (0, 5, 0),
    (2, 0, 0),
]

for n, m, expected in test_cases:
    result = sum_series_robust(n, m)
    status = "✅" if result == expected else "❌"
    print(f"{status} n={n}, m={m}: {result} (expected {expected})")

Generalization: Any Base (ไม่ใช่แค่ Base 10)

def sum_series_base(n, m, base=10):
    """Generalized Series Sum for Any Base"""
    if m <= 0:
        return 0
    # n * (base * (base^m - 1) / (base - 1) - m) / (base - 1)
    # For base=10: n * (10*(10^m-1)/9 - m) / 9
    return n * (base * (base**m - 1) // (base - 1) - m) // (base - 1)

# Binary: n=1, m=4, base=2 -> 1 + 11 + 111 + 1111 (binary)
# = 1 + 3 + 7 + 15 = 26
print(sum_series_base(1, 4, 2))  # 26

# Verify: 1(bin)=1, 11(bin)=3, 111(bin)=7, 1111(bin)=15
print(1 + 3 + 7 + 15)  # 26 ✅

สรุป

  • String Concatenation: เข้าใจง่าย ใช้ได้กับ n หลายหลัก (แต่ช้ากว่า)
  • Mathematical Formula: เร็วที่สุด O(1) เหมาะสำหรับ m ใหญ่
  • Recursion: เข้าใจง่ายแต่มี Recursion Limit
  • Generator: Pythonic, Readable
  • สูตรคณิตศาสตร์: n × (10(10^m - 1)/9 - m) / 9 สำหรับ Base 10