2015-11-10 15 views
13

Tôi biết rằng java.lang.Math cung cấp một tập các phương thức tĩnh để thực hiện một số hoạt động (sum, difference, multiply, increment, decrement, negate, toInt), ném một ArithmeticException trên tràn.Làm thế nào để phát hiện tràn trên điện trong Java

Có điều gì đó tương tự như quyền lực không?

Trả lời

9

Không, không có gì tương đương với pow được tích hợp vào Java. (Các pow phương pháp chỉ xây dựng trong Java là Math.pow, mà chấp nhận đôi và không tràn trong cùng một cách nguyên làm, và BigInteger.pow, mà không làm tràn vì BigInteger s có thể tùy tiện lớn.)

Nếu thư viện của bên thứ ba chấp nhận được, tuy nhiên, Guava có ví dụ IntMath.checkedPow, thực hiện những gì bạn đang tìm kiếm.

+0

Tôi nghĩ bạn cũng nên đề cập đến 'LongMath.checkedPow'. Tôi nghĩ (mặc dù tôi có thể sai) nó tầm thường đối với 'int' bởi vì mỗi' int' có thể được biểu diễn dưới dạng double, vì vậy bạn chỉ cần thực hiện 'Math.pow (a, b)' và so sánh với 'Integer.MAX_VALUE '. –

+0

@Louis Nếu tôi sử dụng 'BigInteger' tôi không thể lo lắng về kích thước của số lượng thu được? – Claudia

+1

@Claudia [BigInteger] (https://docs.oracle.com/javase/8/docs/api/java/math/BigInteger.html): "số nguyên chính xác tùy ý ... Tất cả chi tiết trong Thông số liên quan tràn được bỏ qua, như BigIntegers được thực hiện lớn như cần thiết để chứa các kết quả của một hoạt động. " –

0

Số nguyên chỉ 32 bit. giá trị cực đại là 2^31 -1. (Nếu sử dụng BigInteger.pow. Nó kém hiệu quả hơn.) Vì vậy, bạn có thể kiểm tra thủ công và ném Ngoại lệ nếu được yêu cầu khác sử dụng Math.pow sử dụng gấp đôi.

+3

Đây không phải là câu trả lời. Câu hỏi đặt ra là liệu có một phương thức như vậy (tôi giả định trong Java 8 API). – Turing85

+0

Điều tôi đang cố gắng nói là chúng ta có thể viết mã và mã nguồn riêng của chúng tôi mà không có xây dựng ngoại lệ. cảm ơn. – Chirag

+0

Java hoàn toàn turing, do đó người ta cho rằng bạn có thể viết bất kỳ thuật toán nào trong Java. – Turing85

4

Chirag cho biết, các số nguyên ném ngoại lệ khi chúng tràn trong khi đôi không. Không được quá cụ thể, nhưng về cơ bản, gấp đôi bộ nhớ được lưu trữ rất giống với ký hiệu khoa học, trong đó chúng là số nguyên * 2^(một số sức mạnh), và do đó không bao giờ thực sự tràn nhưng nhân với 2^lớn hoặc nhỏ một số sức mạnh) mà họ hoàn toàn mất đi độ chính xác của họ. Vì vậy, thay vào đó bạn có thể nghĩ về tràn kép vì khi chúng hoàn toàn mất độ chính xác và được in dưới dạng Infinity hoặc -Infinity.

Vì vậy, bạn sẽ cần phải kiểm tra thủ công xem có xảy ra tình trạng tràn không bằng cách kiểm tra xem giá trị kết quả là Double.POSITIVE_INFINITY hoặc Double.NEGATIVE_INFINITY.

Dưới đây là một số mẫu mã để hiển thị những gì tôi muốn nói:

public static void main(String[] args) throws Exception 
{ 
    double a = Double.MAX_VALUE; // highest possible double 
    double b = Double.MAX_VALUE; // highest possible double 

    if (Math.pow(a, b) == Double.POSITIVE_INFINITY || Math.pow(a, b) == Double.NEGATIVE_INFINITY) 
    { 
     throw new ArithmeticException("Double Overflow"); 
    } 
} 
1

Nếu đó là tốt để có thực hiện của riêng bạn, bạn có thể làm một cái gì đó như thế này:

private static final int[] maxBaseForExponent = IntStream.range(0, 30) 
     .map(e -> (int) Math.pow(Integer.MAX_VALUE, 1d/e)).toArray(); 

public static int powExact(int base, int exponent) { 
    if (exponent < 0) { 
     throw new ArithmeticException("Negative exponent"); 
    } 
    if ((base < -1 || base > 1) && (exponent > 30 || base > maxBaseForExponent[exponent]) 
      && !(base == -2 && exponent == 31)) { 
     throw new ArithmeticException("Overflow"); 
    } 
    switch (base) { 
    case -2: 
     return (exponent & 1) == 0 ? 1 << exponent : -1 << exponent; 
    case -1: 
     return (exponent & 1) == 0 ? 1 : -1; 
    case 0: 
     return exponent == 0 ? 1 : 0; 
    case 1: 
     return 1; 
    case 2: 
     return 1 << exponent; 
    default: 
    } 
    int result = 1; 
    while (exponent != 0) { 
     if ((exponent & 1) != 0) { 
      result *= base; 
     } 
     exponent >>= 1; 
     base *= base; 
    } 
    return result; 
} 

Đã thuật toán từ here và sửa đổi nó để kiểm tra tràn bằng cách sử dụng một mảng chứa cơ số tối đa cho mỗi số mũ từ 0 đến 30.

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