У Java, коли ти робиш
a % b
Якщо а негативний, він поверне негативний результат замість того, щоб обертатися навколо b, як слід. Який найкращий спосіб це виправити? Єдиний спосіб я можу подумати
a < 0 ? b + a : a % b
У Java, коли ти робиш
a % b
Якщо а негативний, він поверне негативний результат замість того, щоб обертатися навколо b, як слід. Який найкращий спосіб це виправити? Єдиний спосіб я можу подумати
a < 0 ? b + a : a % b
Відповіді:
Він поводиться так, як слід,% b = a - a / b * b; тобто це залишок.
Ви можете зробити (% b + b)% b
Цей вираз працює як результат (a % b), обов'язково нижчий за b, незалежно від того, aє він позитивним чи негативним. Додавання bвраховує негативні значення a, оскільки (a % b)негативне значення між -bі 0, (a % b + b)обов'язково нижче, ніж bпозитивне. Останній модуль є на випадок, якщо aдля початку було позитивним, оскільки, якщо aпозитивний, (a % b + b)він стане більшим, ніж b. Тому (a % b + b) % bперетворює його на менший, ніж bзнову (і не впливає на негативні aзначення).
(a % b)обов'язково нижчий b(незалежно від того a, позитивний чи негативний), додавання bпіклується про негативні значення a, оскільки (a % b)нижче bі нижче 0, (a % b + b)обов'язково нижче bі позитивних. Останній по модулю є в разі , якщо aбув позитивним для початку, так як якщо aпозитивний (a % b + b)побільшає b. Тому (a % b + b) % bперетворює його на менший, ніж bзнову (і не впливає на негативні aзначення).
a < 0, можливо, ви могли б поглянути)
(a % b + b) % bрозбивається на дуже великі значення aта b. Наприклад, використання a = Integer.MAX_VALUE - 1і b = Integer.MAX_VALUEдасть -3результат, який є негативним числом, чого ви хотіли уникнути.
whileби було повільніше, якщо вам це справді потрібно, за винятком того, що вам потрібен лише той, ifв якому випадку він насправді швидший.
Що стосується Java 8, ви можете використовувати Math.floorMod (int x, int y) та Math.floorMod (довгий х, довгий y) . Обидва ці методи дають ті самі результати, що і відповідь Петра.
Math.floorMod( 2, 3) = 2
Math.floorMod(-2, 3) = 1
Math.floorMod( 2, -3) = -1
Math.floorMod(-2, -3) = -2
floatабо doubleаргументами. Модний бінарний оператор ( %) також працює floatі doubleоперує.
Для тих, хто ще не використовує (або не може використовувати) Java 8, на допомогу Guava прийшов IntMath.mod () , доступний з Guava 11.0.
IntMath.mod( 2, 3) = 2
IntMath.mod(-2, 3) = 1
Одне застереження: на відміну від Math.floorMod () Java 8, дільник (другий параметр) не може бути негативним.
У теорії чисел результат завжди позитивний. Я б здогадався, що це не завжди так у комп’ютерних мовах, оскільки не всі програмісти є математиками. Мої два центи, я вважаю це недоліком дизайну мови, але ви не можете його змінити зараз.
= MOD (-4,180) = 176 = MOD (176, 180) = 176
тому що 180 * (-1) + 176 = -4 те саме, що 180 * 0 + 176 = 176
Використовуючи тут приклад годинника, http://mathworld.wolfram.com/Congruence.html, ви б не сказали, що тривалість_файлу тривалість циклу_довжина становить -45 хвилин, ви б сказали 15 хвилин, хоча обидві відповіді відповідають базовому рівнянню.
-1замість, n-1наприклад,) то майте на це.
У Java 8 є Math.floorMod, але це дуже повільно (її реалізація має кілька підрозділів, множень і умовний). Можливо, що JVM має внутрішню оптимізовану заглушку для цього, однак, це значно пришвидшить його.
Найшвидший спосіб зробити це floorMod, як і деякі інші відповіді тут, але без умовних гілок і лише з однією повільною% оп.
Припустимо, що n позитивний, а х може бути будь-що:
int remainder = (x % n); // may be negative if x is negative
//if remainder is negative, adds n, otherwise adds 0
return ((remainder >> 31) & n) + remainder;
Результати, коли n = 3:
x | result
----------
-4| 2
-3| 0
-2| 1
-1| 2
0| 0
1| 1
2| 2
3| 0
4| 1
Якщо вам потрібно тільки рівномірний розподіл між 0і n-1і не точний мод оператора, і ваші x«s НЕ кластерний поруч 0, наступний буде ще швидше, так як є більш паралелізм на рівні команд і повільне %обчислення відбуватиметься паралельно з іншими частини, оскільки вони не залежать від її результату.
return ((x >> 31) & (n - 1)) + (x % n)
Результати для вищезазначеного n = 3:
x | result
----------
-5| 0
-4| 1
-3| 2
-2| 0
-1| 1
0| 0
1| 1
2| 2
3| 0
4| 1
5| 2
Якщо вхід є випадковим у повному діапазоні int, розподіл обох двох рішень буде однаковим. Якщо вхідні кластери майже до нуля, результатів n - 1в останньому рішенні буде замало .
Ось альтернатива:
a < 0 ? b-1 - (-a-1) % b : a % b
Це може бути або не бути швидшим, ніж інша формула [(a% b + b)% b]. На відміну від іншої формули, вона містить гілку, але використовує одну менш модульну операцію. Можливо, виграш, якщо комп'ютер може правильно передбачити значення <0.
(Редагувати: виправлено формулу.)