2011-11-09 28 views
43

Có cách nào khác trong Java để tính toán công suất của một số nguyên không? Tôi sử dụng Math.pow (a, b) bây giờ, nhưng nó trả về một đôi, và đó thường là rất nhiều công việc, và trông ít sạch khi bạn chỉ muốn sử dụng số nguyên (một quyền lực sau đó sẽ luôn luôn dẫn đến một số nguyên).quyền hạn tính toán trong Java

Có điều gì đơn giản như a ** b như trong Python không?

+2

Đây là bản sao có thể có của câu hỏi này http://stackoverflow.com/questions/101439/the-most-efficient-way-to-implement-an-integer-based-power-function-powint- int – bpgergo

Trả lời

21

Số nguyên chỉ 32 bit. Điều này có nghĩa là giá trị tối đa của nó là 2^31 -1. Như bạn thấy, đối với các số rất nhỏ, bạn quicly có một kết quả mà không thể được đại diện bởi một số nguyên nữa. Đó là lý do Math.pow sử dụng gấp đôi.

Nếu bạn muốn độ chính xác số nguyên tùy ý, hãy sử dụng BigInteger.pow. Nhưng tất nhiên nó kém hiệu quả hơn.

+18

+1, đó là sự thật. Nhưng tôi sẽ xem xét nó tốt đẹp nếu các kiến ​​trúc sư 'Java' đã thêm' pow (int, int) '. Bạn biết đôi khi bạn chỉ muốn rằng '5^6' và không quan tâm đến việc tăng gấp đôi. –

+2

Tôi chỉ đoán, nhưng tôi nghĩ rằng họ không làm điều đó bởi vì một phương pháp như vậy sẽ dẫn đến kết quả hoàn toàn không chính xác trong hầu hết các trường hợp. Nguyên tắc của sự ngạc nhiên ít nhất. –

+1

Vâng, đó là một điểm tốt. Nhưng khi bạn là một người dốt nát và bạn làm việc với 'int', không có gì ngăn bạn chuyển đổi thành' (int) 'một giá trị tràn. –

21

Không, đó không phải là một cái gì đó càng ngắn càng a**b

Dưới đây là một vòng lặp đơn giản, nếu bạn muốn tránh đôi:

long result = 1; 
for (int i = 1; i <= b; i++) { 
    result *= a; 
} 

Nếu bạn muốn sử dụng pow và chuyển đổi kết quả để số nguyên, truyền kết quả như sau:

int result = (int)Math.pow(a, b); 
+11

'O (n)'? Tin xấu ... –

+3

@DmitryGinzburg: đưa ra một 'dài' là 64 bit, sau đó O (n) có 64 là giới hạn trên. Điều đó thực sự rất tệ? –

+0

@Thomas không, bạn sai; nếu 'b' là' 2_000_000_000', thì bạn sẽ phải thực hiện các hoạt động '2e9' thay vì' 31' trong [giải pháp khác] (http://stackoverflow.com/a/20984477/1828937) –

1
import java.util.*; 
public class Power { 

    public static void main(String args[]) 
    { 
     Scanner sc=new Scanner(System.in); 
     int num = 0; 
     int pow = 0; 
     int power = 0; 

     System.out.print("Enter number: "); 
     num = sc.nextInt(); 

     System.out.print("Enter power: "); 
     pow = sc.nextInt(); 

     System.out.print(power(num,pow)); 
    } 
    public static int power(int a, int b) 
    { 
      int power = 1; 
      for(int c=0;c<b;c++) 
      power*=a; 
      return power; 
     } 

} 
+0

Cải thiện vòng lặp 'for':' cho (; b> 0; b -) ' – Doorknob

+6

cải thiện nghiêm trọng: căn cứ vuông và giảm một nửa số mũ ở mỗi bước –

27

Thuật toán tốt nhất dựa trên định nghĩa công suất đệ quy của^b.

long pow (long a, int b) 
{ 
    if (b == 0)  return 1; 
    if (b == 1)  return a; 
    if (isEven(b)) return  pow (a * a, b/2); //even a=(a^2)^b/2 
    else    return a * pow (a * a, b/2); //odd a=a*(a^2)^b/2 

} 

Thời gian chạy của hoạt động là O (logb). Tham chiếu: More information

+0

Và phương thức' isEven (b) 'là gì? Có giống với 'b% 2 == 0' không? – HendraWD

6

Google Guava có các tiện ích toán học cho số nguyên. IntMath

0

Tôi đã quản lý để sửa đổi (ranh giới, thậm chí kiểm tra, kiểm tra số âm) Qx__ answer. Sử dụng có nguy cơ của riêng bạn. 0^-1, 0^-2 vv .. trả về 0.

private static int pow(int x, int n) { 
     if (n == 0) 
      return 1; 
     if (n == 1) 
      return x; 
     if (n < 0) { // always 1^xx = 1 && 2^-1 (=0.5 --> ~ 1) 
      if (x == 1 || (x == 2 && n == -1)) 
       return 1; 
      else 
       return 0; 
     } 
     if ((n & 1) == 0) { //is even 
      long num = pow(x * x, n/2); 
      if (num > Integer.MAX_VALUE) //check bounds 
       return Integer.MAX_VALUE; 
      return (int) num; 
     } else { 
      long num = x * pow(x * x, n/2); 
      if (num > Integer.MAX_VALUE) //check bounds 
       return Integer.MAX_VALUE; 
      return (int) num; 
     } 
    } 
2

thư viện toán học ổi của cung cấp hai phương pháp này rất hữu ích khi tính cường quốc nguyên chính xác:

pow(int b, int k) tính toán b đến thứ k sức mạnh, và kết thúc tốt đẹp trên tràn

checkedPow(int b, int k) là giống hệt nhau ngoại trừ việc nó ném ArithmeticException trên tràn

Cá nhân checkedPow() đáp ứng hầu hết nhu cầu của tôi cho số nguyên lũy thừa và được sạch và SAFT er hơn sử dụng các phiên bản đôi và làm tròn, vv Trong hầu như tất cả những nơi tôi muốn có một chức năng quyền lực, tràn là một lỗi (hoặc không thể, nhưng tôi muốn được nói nếu không thể trở thành có thể).

Nếu bạn muốn nhận được kết quả long, bạn chỉ có thể sử dụng các phương pháp LongMath tương ứng và vượt qua các đối số int.

2

Bạn có thể chỉ cần sử dụng Math.pow(a,b) như bạn đã sử dụng trước đó và chỉ chuyển đổi giá trị của nó bằng cách sử dụng (int) trước đó. Dưới đây có thể được sử dụng làm ví dụ cho nó.

int x = (int) Math.pow(a,b); 

nơi ab có thể double hoặc int giá trị như bạn muốn. Điều này sẽ chỉ đơn giản là chuyển đổi đầu ra của nó thành một giá trị số nguyên như bạn yêu cầu.

+0

Tôi không đồng ý, nếu '3.0^1.0 = 2.999999 ...' do lỗi làm tròn, câu trả lời sẽ là '2' sai. – Hidde

+0

@Hidde Có, bạn là người bạn đúng này chắc chắn có một nhược điểm, cảm ơn đã đề cập đến. Nó có thể cho kết quả sai nhưng có lẽ ví dụ của bạn ở đây sẽ cho kết quả chính xác là '3.0'.Chỉ cần làm ví dụ để làm tròn lỗi cho phép nhân' 2.2 * 3.0 = 6.0000005' thay vì '6.6'. –

+0

@Hidde Một Java 'double' có thể đại diện cho tất cả Java' ints' chính xác. Xem đặc tả ngôn ngữ Java, phần 5.1.2, "[Mở rộng chuyển đổi nguyên thủy] (https://docs.oracle.com/javase/specs/jls/se9/html/jls-5.html#jls-5.1.2) ". –

1

Một đơn giản (không có kiểm tra cho tràn hoặc tính hợp lệ của các đối số) thực hiện cho lặp đi lặp lại-bình phương thuật toán để tính toán sức mạnh:

/** Compute a**p, assume result fits in a 32-bit signed integer */ 
int pow(int a, int p) 
{ 
    int res = 1; 
    int i1 = 31 - Integer.numberOfLeadingZeros(p); // highest bit index 
    for (int i = i1; i >= 0; --i) { 
     res *= res; 
     if ((p & (1<<i)) > 0) 
      res *= a; 
    } 
    return res; 
} 

Sự phức tạp thời gian là logarit để mũ p (tức là tuyến tính với số các bit cần thiết để biểu diễn p).

0

Không giống như Python (trong đó quyền hạn có thể được tính bằng ** b), JAVA không có cách tắt như vậy để hoàn thành kết quả sức mạnh của hai số. Java có hàm có tên pow trong lớp Toán, mà trả về một giá trị đúp

double pow(double base, double exponent) 

Nhưng bạn cũng có thể tính toán, quyền hạn của số nguyên bằng cách sử dụng chức năng tương tự. Trong chương trình sau tôi đã làm như vậy và cuối cùng tôi chuyển đổi kết quả thành một số nguyên (typecasting). Thực hiện theo ví dụ:

import java.util.*; 
import java.lang.*; // CONTAINS THE Math library 
public class Main{ 
    public static void main(String[] args){ 
     Scanner sc = new Scanner(System.in); 
     int n= sc.nextInt(); // Accept integer n 
     int m = sc.nextInt(); // Accept integer m 
     int ans = (int) Math.pow(n,m); // Calculates n^m 
     System.out.println(ans); // prints answers 
    } 
} 

Ngoài ra, Các java.math.BigInteger.pow(int exponent) trả về một BigInteger có giá trị là (điều này^mũ). Số mũ là số nguyên chứ không phải là BigInteger. Ví dụ:

import java.math.*; 
public class BigIntegerDemo { 
public static void main(String[] args) { 
     BigInteger bi1, bi2; // create 2 BigInteger objects   
     int exponent = 2; // create and assign value to exponent 
     // assign value to bi1 
     bi1 = new BigInteger("6"); 
     // perform pow operation on bi1 using exponent 
     bi2 = bi1.pow(exponent); 
     String str = "Result is " + bi1 + "^" +exponent+ " = " +bi2; 
     // print bi2 value 
     System.out.println(str); 
    } 
} 
1

Khi đó là sức mạnh của 2. Hãy nhớ rằng bạn có thể sử dụng đơn giản và nhanh chóng 1 < < mũ ví dụ.

2^2 == (int) Math.pow(2,2) == 1 << 2 
2^10 == (int) Math.pow(2,10) == 1 << 10 

Đối với số mũ lớn hơn (trên 31) sử dụng dài thay vì

2^32 == (long) Math.pow(2,32) == 1L << 32 

btw. trong Kotlin bạn có shl thay vì << nên

1L << 32 == 1L shl 32 
0

Sử dụng logic dưới đây để tính toán sức mạnh n của a.

Thông thường, nếu chúng tôi muốn tính toán n của a. Chúng ta sẽ nhân số 'a' với số lần n.Thời gian phức tạp của phương pháp này sẽ là O (n) Chia năng lượng n cho 2, tính lũy thừa lũy thừa = nhân 'a' cho đến n/2. Tăng gấp đôi giá trị. Bây giờ Độ phức tạp thời gian được giảm xuống O (n/2).

public int calculatePower1(int a, int b) { 
      if (b == 0) { 
       return 1; 
      } 

      int val = (b % 2 == 0) ? (b/2) : (b - 1)/2; 


      int temp = 1; 
      for (int i = 1; i <= val; i++) { 
       temp *= a; 
      } 


      if (b % 2 == 0) { 
       return temp * temp; 
      } else { 
       return a * temp * temp; 
      } 

     } 
+0

Cảm ơn, nhưng tôi đang tìm một cách được xây dựng thành ngôn ngữ và ngắn gọn. Tôi biết thuật toán để tính toán quyền hạn. – Hidde

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