2010-08-26 42 views
20

Trong dự án nhỏ của tôi, tôi cần phải làm một cái gì đó giống như Math.pow (7777.66, 5555.44) chỉ với số lượng rất lớn. Tôi đã xem qua một số giải pháp:Làm thế nào để làm một sức mạnh phân đoạn trên BigDecimal trong Java?

  • Sử dụng đôi - nhưng số lượng quá lớn
  • Sử dụng BigDecimal.pow nhưng không hỗ trợ cho phân đoạn
  • Sử dụng X^(A + B) = X^Một * Công thức X^B (B là phần còn lại của chữ số thứ hai), nhưng lại không hỗ trợ cho chữ X lớn hoặc A vì tôi vẫn chuyển đổi thành đôi
  • Sử dụng một số thuật toán chuỗi Taylor hoặc một cái gì đó tương tự - Tôi không giỏi môn toán vì vậy đây là tùy chọn cuối cùng của tôi nếu tôi không tìm thấy bất kỳ giải pháp nào (một số thư viện hoặc công thức cho (A + B)^(C + D)).

Có ai biết thư viện hoặc giải pháp dễ dàng không? Tôi thấy rằng nhiều người đối phó với cùng một vấn đề ...

p.s. Tôi tìm thấy một số thư viện được gọi là ApFloat tuyên bố làm điều đó xấp xỉ, nhưng kết quả tôi nhận được gần đúng đến mức thậm chí 8^2 đã cho tôi 60 ...

+0

bạn có thể đưa ra một ví dụ về những gì bạn cố gắng để hoàn thành, 8^2 = 64 âm thanh người nghèo và 2^100^100 cần phải được thu nhỏ lại. – stacker

+0

Tôi phải nói rằng tôi đã thử công thức lừa, và nó hoạt động tốt cho đến nay ngay cả với con số với hàng triệu chữ số! (Có vẻ như tôi không biết mọi thứ về đôi và int) ... Ví dụ: 50!^10! = 12.50911317862076252364259 * 10^233996181 50!^0.06 = 7395.788659356498101260513 Mã này hơi dài để đăng ở đây, nhưng bạn có ý tưởng về X^(A + B) = X^A * X^B ... Bây giờ Tôi đang cố gắng để hiểu làm thế nào và tại sao (và nếu) nó thực sự làm việc với những con số khổng lồ. –

+0

Tôi đã đưa ra giải pháp ở đó http://stackoverflow.com/questions/11848887/bigdecimal-to-the-power-of-bigdecimal-on-java-android/22556217#22556217 –

Trả lời

21

Giải pháp cho các đối số dưới 1.7976931348623157E308 (Double.MAX_VALUE) nhưng kết quả hỗ trợ với hàng triệu chữ số:

Kể từ số hỗ trợ tăng gấp đôi lên đến MAX_VALUE (ví dụ, 100! trong hình dạng kép như thế này: 9.332621544394415E157), không có vấn đề gì khi sử dụng BigDecimal.doubleValue(). Nhưng bạn không nên chỉ làm Math.pow (double, double) vì nếu kết quả lớn hơn MAX_VALUE, bạn sẽ chỉ nhận được vô cùng. SO: sử dụng công thức X^(A + B) = X^A * X^B để tách phép tính thành HAI quyền hạn, lớn, sử dụng BigDecimal.pow và nhỏ (còn lại của đối số thứ 2), sử dụng Math. pow, sau đó nhân lên. X sẽ được sao chép sang DOUBLE - đảm bảo nó không lớn hơn MAX_VALUE, A sẽ là INT (tối đa 2147483647 nhưng BigDecimal.pow không hỗ trợ số nguyên hơn một tỷ anyway), và B sẽ tăng gấp đôi, luôn nhỏ hơn 1. Bằng cách này bạn có thể làm như sau (bỏ qua hằng tôi tin vv):

int signOf2 = n2.signum(); 
    try { 
     // Perform X^(A+B)=X^A*X^B (B = remainder) 
     double dn1 = n1.doubleValue(); 
     // Compare the same row of digits according to context 
     if (!CalculatorUtils.isEqual(n1, dn1)) 
      throw new Exception(); // Cannot convert n1 to double 
     n2 = n2.multiply(new BigDecimal(signOf2)); // n2 is now positive 
     BigDecimal remainderOf2 = n2.remainder(BigDecimal.ONE); 
     BigDecimal n2IntPart = n2.subtract(remainderOf2); 
     // Calculate big part of the power using context - 
     // bigger range and performance but lower accuracy 
     BigDecimal intPow = n1.pow(n2IntPart.intValueExact(), 
       CalculatorConstants.DEFAULT_CONTEXT); 
     BigDecimal doublePow = 
      new BigDecimal(Math.pow(dn1, remainderOf2.doubleValue())); 
     result = intPow.multiply(doublePow); 
    } catch (Exception e) { 
     if (e instanceof CalculatorException) 
      throw (CalculatorException) e; 
     throw new CalculatorException(
      CalculatorConstants.Errors.UNSUPPORTED_NUMBER_ + 
       "power!"); 
    } 
    // Fix negative power 
    if (signOf2 == -1) 
     result = BigDecimal.ONE.divide(result, CalculatorConstants.BIG_SCALE, 
       RoundingMode.HALF_UP); 

Kết quả ví dụ:

50!^10! = 12.50911317862076252364259*10^233996181 

50!^0.06 = 7395.788659356498101260513 
+2

Điều này không hữu ích nếu không có các lớp 'CalculatorUtils',' CalculatorConstants' hoặc 'CalculatorException' – Supuhstar

+0

Nếu ví dụ không hữu ích không sử dụng nó, đó là một ví dụ. Đây là lý do tại sao tôi đã viết "bỏ qua hằng số riêng tư của tôi". Bạn có thể đoán hoặc thay thế từng người trong số họ. –

0

Exponents = logarithms.

Hãy xem Logarithm of a BigDecimal

+2

Eh? Họ chắc chắn không phải là từ đồng nghĩa nếu đó là những gì bạn đang nói ... –

+0

Mã nguồn được gọi là câu trả lời được chấp nhận của câu hỏi này có nhiều giải pháp hơn là chỉ cho nhật ký tự nhiên. – prunge

+1

@Prunge - Cảm ơn. Tôi chưa từng nói gì về khúc gỗ tự nhiên.Thực sự, nếu bạn nhìn vào câu trả lời được chấp nhận của Gene Marin, những gì anh ta mô tả là lôgarit. X^(A + B) = X^A * X^B tương đương với ghi log (base X) A + log (base X) B = log (base X) (A * B). Điều này sẽ cho phép bạn mang các con số đến một mức độ có thể quản lý được. –

Các vấn đề liên quan