2012-09-10 52 views
5

Tôi gặp sự cố khi phát hiện xem tổng/nhân của hai số có vượt quá giá trị lớn nhất của số nguyên dài hay không. đang
Ví dụ:số java vượt quá long.max_value - cách phát hiện?

long a = 2 * Long.MAX_VALUE; 
System.out.println("long.max * smth > long.max... or is it? a=" + a); 

này mang lại cho tôi -2, trong khi tôi mong chờ nó để ném một NumberFormatException ...

Có một cách đơn giản để làm công việc này? Bởi vì tôi có một số mã mà nhân trong các khối IF lồng nhau hoặc bổ sung trong một vòng lặp và tôi sẽ ghét thêm nhiều IFs cho mỗi IF hoặc bên trong vòng lặp.

Chỉnh sửa: oh well, có vẻ như câu trả lời này từ một câu hỏi khác là thích hợp nhất cho những gì tôi cần: https://stackoverflow.com/a/9057367/540394
Tôi không muốn làm boxing/unboxing vì nó thêm overhead unnecassary, và cách này là rất ngắn, đó là một điểm cộng lớn đối với tôi. Tôi sẽ chỉ viết hai hàm ngắn để thực hiện các kiểm tra này và trả lại số phút tối thiểu hoặc cực đại.

Edit2: đây là chức năng để hạn chế một chặng đường dài để min/giá trị tối đa của nó theo câu trả lời tôi liên kết với trên:

/** 
* @param a : one of the two numbers added/multiplied 
* @param b : the other of the two numbers 
* @param c : the result of the addition/multiplication 
* @return the minimum or maximum value of a long integer if addition/multiplication of a and b is less than Long.MIN_VALUE or more than Long.MAX_VALUE 
*/ 
public static long limitLong(long a, long b, long c) 
{ 
    return (((a > 0) && (b > 0) && (c <= 0)) 
     ? Long.MAX_VALUE 
     : (((a < 0) && (b < 0) && (c >= 0)) ? Long.MIN_VALUE : c)); 
} 

Nói cho tôi biết nếu bạn nghĩ rằng đây là sai.

+0

+1. Nên có một số thư viện cho phép phát hiện tràn số nguyên. – Thilo

+0

Hoặc các khối đặc biệt (giống như cuối cùng?) Có thể giúp các nhà phát triển kích hoạt hành vi lỗi tràn trên cho tất cả các mã toán thực thi bên trong. Tôi tin rằng C# có một. EDIT: Tìm thấy nó, [kiểm tra và bỏ chọn các khối trong C#] (http://msdn.microsoft.com/en-us/library/a569z7k8.aspx). –

+0

Vâng, C# dường như ném lỗi trên tràn (mà tôi muốn rất nhiều thích hơn im lặng và kết quả sai mà không có ý nghĩa với tôi) ... – jurchiks

Trả lời

4

Nếu bạn không chắc chắn kết quả sẽ nhỏ hơn 9 nghìn tỷ nghìn tỷ, tôi sẽ sử dụng double hoặc BigInteger Nhận lỗi không giúp bạn rất nhiều vì bạn vẫn cần phải biết phải làm gì.

Tốt hơn hết là bạn không gặp lỗi ở địa điểm đầu tiên bằng cách xác thực thông tin nhập của bạn để đảm bảo chúng nằm trong phạm vi và nếu phạm vi kết quả lớn hơn long hãy sử dụng loại có thể xử lý điều này.

Với BigInteger bạn có thể làm

BigInteger a = BigInteger.valueOf(2).multiply(BigInteger.valueOf(Long.MAX_VALUE)); 
long l = a.longValue(); 
if (a.compareTo(BigInteger.valueOf(l)) == 0) { 
    // ok 
} else { 
    // error 
} 

Với đôi bạn có thể làm

double d = 2.0 * Long.MAX_VALUE; 
long l = (long) Math.max(Long.MIN_VALUE, Math.min(Long.MAX_VALUE, d)); 
// or as a helper method. 
long l = boundedCast(d); 

Lưu ý: sử dụng double thay vì dài có thể dẫn đến một số thiệt hại chính xác.

Tôi muốn tránh sự cần thiết của một khối lỗi ở địa điểm đầu tiên.

+1

Vấn đề là, tôi cần phải cắt nó xuống thành 'long' nếu nó vượt quá nó. Có lẽ điều đó sẽ giúp ích? Nhận được một lỗi sẽ giúp rất nhiều trong trường hợp của tôi; Tôi chỉ có thể đặt toàn bộ mã trong một khối try/catch và nếu một lỗi được ném, hãy đặt giá trị thành Long.MAX_VALUE, bởi vì đó là tất cả những gì tôi cần. – jurchiks

+0

Nếu nó quá dài, bạn không thể cắt nó. Điều tốt nhất bạn có thể làm là làm cho nó 'Long.MAX_VALUE' không phải là một giải pháp tuyệt vời. –

+3

@PeterLawrey Tôi nghĩ rằng hãy đặt nó thành 'Long.MAX_VALUE' là ý nghĩa của OP * cắt xuống thành' long' *. – brimborium

2

Exceding giá trị tối đa của một long doesnt ném một ngoại lệ, thay vào đó nó cicles trở lại. Nếu bạn làm điều này:

Dài.MAX_VALUE + 1

bạn sẽ nhận thấy kết quả tương đương với Long.MIN_VALUE.

Nếu bạn muốn nó để ném một kiểm tra ngoại lệ nếu nó đạt giá trị tối đa và ném ngoại lệ

[Chỉnh sửa]

Bạn cũng có thể sử dụng Guava Library để kiểm tra nếu có một tràn bộ nhớ khi bạn tổng hai thời gian dài;

long c = LongMath.checkedAdd(a, b); 

điều này sẽ ném ngoại lệ khi xảy ra tràn khi tổng kết hai thời lượng.

Bạn có thể tìm javadoc here

+2

"chỉ cần làm một nếu kiểm tra nếu nó đạt đến giá trị tối đa" - và làm thế nào để bạn tưởng tượng rằng? Tôi không muốn ném ngoại lệ bản thân mình, tôi không nên, để được chính xác. – jurchiks

+0

Bạn cũng có thể thử điều này: long c = LongMath.checkedAdd (a, b); Nó ném một ngoại lệ nếu có một tràn khi tổng hợp 2 longs –

+1

@ DanielA. Có lẽ bạn nên thêm, rằng bạn cần [Thư viện ổi] (http://code.google.com/p/guava-libraries/) cho việc này. – Baz

-1

Long giá trị vượt MAX_VALUE không ném bất kỳ ngoại lệ. Bạn cần kiểm tra và xử lý các tình huống như vậy theo cách thủ công.

Mặc dù @PeterLawrey đề xuất bạn nên cân nhắc sử dụng doubleBigInteger.

+0

Làm thế nào để bạn làm điều này với một đôi? Một ví dụ BigInteger đã được đăng, nhưng đôi ... Chỉ định một giá trị gấp đôi Long.MAX_VALUE và in nó mang lại cho tôi '9.223372036854776E18'. – jurchiks

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