Weird Objective-C Поведение мод для отрицательных чисел

Итак, я думал, что отрицательные числа, когда mod'ed должны быть помещены в положительное пространство... Я не могу заставить это произойти в objective-c

Я ожидаю этого:

-1 % 3 = 2
 0 % 3 = 0
 1 % 3 = 1
 2 % 3 = 2

Но получим это

-1 % 3 = -1
 0 % 3 = 0
 1 % 3 = 1
 2 % 3 = 2

Почему это и есть обходное решение?

Ответ 1

result = n % 3;
if( result < 0 ) result += 3;

Не выполняйте дополнительные операции mod, как предложено в других ответах. Они очень дороги и не нужны.

Ответ 2

В C и Objective-C операторы деления и модуля выполняют усечение до нуля. a / b floor(a / b), если a / b > 0, в противном случае это ceiling(a / b), если a / b < 0. Всегда бывает, что a == (a / b) * b + (a % b), если, конечно, b равно 0. Как следствие, positive % positive == positive, positive % negative == positive, negative % positive == negative и negative % negative == negative (вы можете выработать логику для всех 4 случаев, хотя это немного сложно).

Ответ 3

Если n имеет ограниченный диапазон, то вы можете получить желаемый результат просто, добавив известную константу, кратную 3, которая больше, чем абсолютное значение минимума.

Например, если n ограничено -1000..2000, вы можете использовать выражение:

result = (n+1002) % 3;

Убедитесь, что максимум плюс ваша константа не будет переполняться при суммировании.

Ответ 4

У нас есть проблема языка:

math-er-says: i take this number plus that number mod other-number
code-er-hears: I add two numbers and then devide the result by other-number
code-er-says: what about negative numbers?
math-er-says: WHAT? fields mod other-number don't have a concept of negative numbers?
code-er-says: field what? ...
  • Математика в этих беседах говорит о выполнении математики в круговой числовой строке. Если вы вычтите снизу, вы оберните его вверх.
  • пользователь кода говорит об операторе, который вычисляет остаток.

В этом случае вам нужен оператор modhematician mod и функция остатка в вашем распоряжении. вы можете преобразовать оператор остатка в оператор модема математика, проверив, чтобы каждый раз, когда вы делаете вычитание, вы падаете снизу.

Ответ 5

Я бы тоже ожидал положительного числа, но я нашел это из ISO/IEC 14882: 2003: Языки программирования - С++, 5.6.4 (найдено в Статья в Википедии об операции с модулем):

Двоичный оператор% дает остаток от деления первого выражения на второй..... Если оба операнда неотрицательны, то остаток неотрицателен; если нет, знак остатка определяется реализацией

Ответ 6

Если это будет поведение, и вы знаете, что это будет, то для m % n = r просто используйте r = n + r. Если вы не знаете, что здесь произойдет, используйте r = r % n.

Изменить: Подводя итог, используйте r = ( n + ( m % n ) ) % n

Ответ 7

JavaScript тоже делает это. Я был пойман этим пару раз. Подумайте об этом как о отражении вокруг нуля, а не о продолжении.

Ответ 8

Почему: потому что это то, как оператор mod указан в C-стандарте (помните, что Objective-C является расширением C). Это смущает большинство людей, которых я знаю (например, я), потому что это удивительно, и вы должны помнить об этом.

Что касается обходного пути: я бы использовал uncleo's.

Ответ 9

Ответ на UncleO, вероятно, более надежный, но если вы хотите сделать это в одной строке, и вы уверены, что отрицательное значение не будет более отрицательным, чем одна итерация мода (например, если вы только когда-либо вычитая значение мода в любое время), вы можете упростить его до одного выражения:

int result = (n + 3) % 3;

Поскольку вы все равно выполняете mod, добавление 3 к начальному значению не имеет эффекта, если n отрицательно (но не менее -3), и в этом случае результат будет ожидаемым положительным модулем.

Ответ 10

Для остатка есть два варианта, и знак зависит от языка. ANSI C выбирает знак дивиденда. Я бы заподозрил, что именно поэтому вы видите Objective-C. См. также запись в википедии.

Ответ 11

Не только java script, почти все языки показывают неправильный ответ ' то, что сказал coneybeare, правильно, когда у нас есть режим, мы должны получить остаток Остаток - это ничего, что остается после деления, и оно должно быть положительным целым числом.

Если вы проверите цифровую строку, вы поймете, что

Я также сталкиваюсь с той же проблемой в VB, и это заставило меня принудительно добавить дополнительную проверку, например если результат является отрицательным, мы должны добавить делитель к результату

Ответ 12

Вместо a%b

Использование: a-b*floor((float)a/(float)b)

Вы ожидаете остаток и используете modulo. В математике они одно и то же, в C они разные. GNU-C имеет Rem() и Mod(), objective-c имеет только mod(), поэтому вам придется использовать приведенный выше код для имитации функции rem (что совпадает с модом в математическом мире, но не в программировании world [для большинства языков как минимум])


Также обратите внимание, что для этого можно определить простой в использовании макрос.

#define rem(a,b) ((int)(a-b*floor((float)a/(float)b)))

Тогда вы могли бы просто использовать rem(-1,3) в своем коде, и он должен работать нормально.