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

คำนวณค่ายกกำลัง (Power/Exponent) ใน C#

การคำนวณ $base^{exponent}$ ใน C# มีหลายวิธี ตั้งแต่ Built-in Method จนถึง Custom Implementation

วิธีที่ 1: Math.Pow (Built-in - Double)

using System;

double n = 7;
double p = 3;
double res = Math.Pow(n, p);  // 343.0

Console.WriteLine($"Exponent Power = {n}");
Console.WriteLine($"Result = {res}");

ผลลัพธ์

Exponent Power= 7
Result= 343

⚠️ ข้อควรระวังกับ Math.Pow

  • รับและคืนค่า **double** - อาจมี Precision Error กับจำนวนเต็มใหญ่
  • ตัวอย่าง: Math.Pow(10, 15) อาจได้ 999999999999999.9 แทน 1000000000000000
  • ไม่รองรับ Negative Base กับ Fractional Exponent (NaN)

วิธีที่ 2: Integer Power (Exact - No Precision Loss)

A. Simple Loop (O(n))

public static long IntPow(long base, int exp) {
    if (exp < 0) throw new ArgumentException("Negative exponent");
    long result = 1;
    for (int i = 0; i < exp; i++) result *= base;
    return result;
}

B. Exponentiation by Squaring (O(log n) - แนะนำ)

public static long IntPowFast(long base, int exp) {
    if (exp < 0) throw new ArgumentException("Negative exponent not supported for integers");
    
    long result = 1;
    while (exp > 0) {
        if ((exp & 1) == 1)  // exp is odd
            result *= base;
        base *= base;
        exp >>= 1;  // exp /= 2
    }
    return result;
}

// Trace: 5^13
// exp=13(odd) result=5    base=25   exp=6
// exp=6(even) result=5    base=625  exp=3
// exp=3(odd)  result=3125 base=390625 exp=1
// exp=1(odd)  result=1220703125 base=... exp=0
// Done

C. Recursive (Clean but Stack Overhead)

public static long IntPowRecursive(long base, int exp) {
    if (exp == 0) return 1;
    if (exp == 1) return base;
    
    long half = IntPowRecursive(base, exp / 2);
    if (exp % 2 == 0)
        return half * half;
    else
        return half * half * base;
}

วิธีที่ 3: BigInteger (Unlimited Size)

using System.Numerics;

public static BigInteger BigPow(BigInteger base, int exp) {
    if (exp < 0) throw new ArgumentException("Negative exponent");
    
    BigInteger result = 1;
    while (exp > 0) {
        if ((exp & 1) == 1) result *= base;
        base *= base;
        exp >>= 1;
    }
    return result;
}

// 2^1000
var huge = BigPow(2, 1000);  // 301 digits

วิธีที่ 4: Bit Shifting (เฉพาะ Power of 2)

// 2^n = 1 << n (Bit Shift)
int pow2_10 = 1 << 10;  // 1024
long pow2_60 = 1L << 60;  // 1,152,921,504,606,846,976

// ใช้ได้เฉพาะ Base = 2 และ Exponent >= 0

Benchmark (10^10)

Method Time Complexity Precision Use Case
Math.Pow O(1) Hardware Double (~15 digits) Scientific, Float, Fractional Exp
Simple Loop O(n) Exact (Integer) Small Exponent (< 30)
Exponentiation by Squaring O(log n) Exact (Integer) General Integer Power ✅ Best
BigInteger O(log n) × M(n) Exact (Unlimited) Very Large Numbers
Bit Shift (1 << n) O(1) Exact Power of 2 Only

Negative Exponents

// Math.Pow รองรับ Negative Exponent
double result = Math.Pow(2, -3);  // 0.125

// Integer Power - ไม่รองรับ Negative (ต้องคืน Fraction)
// ใช้ double หรือ Rational/BigRational Library แทน

Best Practice Helper Class

public static class MathUtils {
    // Integer Power - Fast & Exact
    public static long Pow(long base, int exp) {
        if (exp < 0) throw new ArgumentOutOfRangeException(nameof(exp));
        long result = 1;
        while (exp > 0) {
            if ((exp & 1) == 1) result *= base;
            base *= base;
            exp >>= 1;
        }
        return result;
    }
    
    // Safe Power with Overflow Check
    public static long PowChecked(long base, int exp) {
        long result = 1;
        while (exp > 0) {
            if ((exp & 1) == 1) checked { result *= base; }
            checked { base *= base; }
            exp >>= 1;
        }
        return result;
    }
}