2010-12-10 19 views
78

Trong java khi bạn làmCách tốt nhất để làm cho mô đun của Java hoạt động như thế nào với các số âm?

a % b 

Nếu a là tiêu cực, nó sẽ trả về một kết quả tiêu cực, thay vì gói xung quanh để b như nó nên. Cách tốt nhất để khắc phục điều này là gì? Cách duy nhất tôi có thể nghĩ là

a < 0 ? b + a : a % b 
+10

Không có hành vi mô-đun "đúng" khi xử lý các số âm - nhiều ngôn ngữ làm theo cách này, nhiều ngôn ngữ làm khác nhau và một vài ngôn ngữ làm điều gì đó hoàn toàn khác. Ít nhất hai người đầu tiên có ưu và khuyết điểm của họ. – delnan

+3

điều này thật kỳ lạ đối với tôi. tôi nghĩ rằng nó chỉ nên trả về âm nếu b là âm. – fent

+1

có thể trùng lặp của [Làm thế nào để thực hiện các phép tính modulus với số âm?] (Http://stackoverflow.com/questions/4403542/how-does-java-do-modulus-calculations-with-negative-numbers) –

Trả lời

110

Nó hoạt động như nó phải là% b = a - a/b * b; tức là phần còn lại.

Bạn có thể làm (% b + b)% b


biểu hiện này hoạt động như là kết quả của (a % b) nhất thiết phải thấp hơn b, bất kể nếu a là tích cực hay tiêu cực. Thêm b sẽ xử lý các giá trị âm của a, kể từ (a % b) là giá trị âm giữa -b0, (a % b + b) nhất thiết phải thấp hơn b và dương. Modulo cuối cùng có trong trường hợp a là tích cực để bắt đầu, vì nếu a là dương (a % b + b) sẽ trở nên lớn hơn b. Do đó, (a % b + b) % b biến nó thành nhỏ hơn b một lần nữa (và không ảnh hưởng đến giá trị âm a âm).

+3

hoạt động tốt hơn. và nó hoạt động cho các số âm lớn hơn nhiều so với b. – fent

+0

đây là một câu trả lời thực sự tốt! gần như thanh lịch như java sẽ cho phép bạn đi, tôi nghĩ rằng – mfrankli

+0

@PeterLawrey - Cảm ơn, tôi cũng cần giải pháp này, nhưng bạn có sẵn sàng giải thích tại sao nó hoạt động không? – Lou

53

Kể từ Java 8, bạn có thể sử dụng Math.floorMod(int x, int y)Math.floorMod(long x, long y). Cả hai phương pháp này đều trả lại kết quả tương tự như câu trả lời của Peter.

Math.floorMod(2, 3) = 2 
Math.floorMod(-2, 3) = 1 
Math.floorMod(2, -3) = -1 
Math.floorMod(-2, -3) = -2 
+0

câu trả lời hay nhất cho Java 8+ – charneykaye

8

Đối với những người không sử dụng (hoặc không thể sử dụng) Java 8, Guava đã giải cứu với IntMath.mod(), có sẵn từ Guava 11.0.

IntMath.mod(2, 3) = 2 
IntMath.mod(-2, 3) = 1 

Một caveat: không giống như Java 8's Math.floorMod(), số chia (tham số thứ hai) không được âm.

5

Trong lý thuyết số, kết quả luôn dương. Tôi đoán rằng điều này không phải luôn luôn như vậy trong ngôn ngữ máy tính bởi vì không phải tất cả các lập trình viên đều là các nhà toán học. Hai xu của tôi, tôi sẽ coi nó là một khiếm khuyết thiết kế của ngôn ngữ, nhưng bạn không thể thay đổi nó ngay bây giờ.

= MOD (-4.180) = 176 = MOD (176, 180) = 176

vì 180 * (-1) + 176 = -4 giống như 180 * 0 + 176 = 176

Sử dụng ví dụ đồng hồ ở đây, http://mathworld.wolfram.com/Congruence.html bạn sẽ không nói duration_of_time mod cycle_length là -45 phút, bạn sẽ nói 15 phút, mặc dù cả hai câu trả lời đều thỏa mãn phương trình cơ sở.

0

Tôi thích biểu thức này:

a < 0 ? b - (-a) % b : a % b 

này có thể hoặc có thể không nhanh hơn so với công thức khác [(a% b + b)% b], đến để suy nghĩ về nó. Nó chứa một nhánh mà thường là xấu với các bộ vi xử lý hiện đại, nhưng sử dụng một hoạt động ít modulo hơn.

Thực ra nó có thể chậm hơn.