Ответ 1
result = n % 3;
if( result < 0 ) result += 3;
Не выполняйте дополнительные операции mod, как предложено в других ответах. Они очень дороги и не нужны.
Итак, я думал, что отрицательные числа, когда 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
Почему это и есть обходное решение?
result = n % 3;
if( result < 0 ) result += 3;
Не выполняйте дополнительные операции mod, как предложено в других ответах. Они очень дороги и не нужны.
В 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 случаев, хотя это немного сложно).
Если n имеет ограниченный диапазон, то вы можете получить желаемый результат просто, добавив известную константу, кратную 3, которая больше, чем абсолютное значение минимума.
Например, если n ограничено -1000..2000, вы можете использовать выражение:
result = (n+1002) % 3;
Убедитесь, что максимум плюс ваша константа не будет переполняться при суммировании.
У нас есть проблема языка:
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 и функция остатка в вашем распоряжении. вы можете преобразовать оператор остатка в оператор модема математика, проверив, чтобы каждый раз, когда вы делаете вычитание, вы падаете снизу.
Я бы тоже ожидал положительного числа, но я нашел это из ISO/IEC 14882: 2003: Языки программирования - С++, 5.6.4 (найдено в Статья в Википедии об операции с модулем):
Двоичный оператор% дает остаток от деления первого выражения на второй..... Если оба операнда неотрицательны, то остаток неотрицателен; если нет, знак остатка определяется реализацией
Если это будет поведение, и вы знаете, что это будет, то для m % n = r
просто используйте r = n + r
. Если вы не знаете, что здесь произойдет, используйте r = r % n
.
Изменить: Подводя итог, используйте r = ( n + ( m % n ) ) % n
JavaScript тоже делает это. Я был пойман этим пару раз. Подумайте об этом как о отражении вокруг нуля, а не о продолжении.
Почему: потому что это то, как оператор mod указан в C-стандарте (помните, что Objective-C является расширением C). Это смущает большинство людей, которых я знаю (например, я), потому что это удивительно, и вы должны помнить об этом.
Что касается обходного пути: я бы использовал uncleo's.
Ответ на UncleO, вероятно, более надежный, но если вы хотите сделать это в одной строке, и вы уверены, что отрицательное значение не будет более отрицательным, чем одна итерация мода (например, если вы только когда-либо вычитая значение мода в любое время), вы можете упростить его до одного выражения:
int result = (n + 3) % 3;
Поскольку вы все равно выполняете mod, добавление 3 к начальному значению не имеет эффекта, если n отрицательно (но не менее -3), и в этом случае результат будет ожидаемым положительным модулем.
Для остатка есть два варианта, и знак зависит от языка. ANSI C выбирает знак дивиденда. Я бы заподозрил, что именно поэтому вы видите Objective-C. См. также запись в википедии.
Не только java script, почти все языки показывают неправильный ответ ' то, что сказал coneybeare, правильно, когда у нас есть режим, мы должны получить остаток Остаток - это ничего, что остается после деления, и оно должно быть положительным целым числом.
Если вы проверите цифровую строку, вы поймете, что
Я также сталкиваюсь с той же проблемой в VB, и это заставило меня принудительно добавить дополнительную проверку, например если результат является отрицательным, мы должны добавить делитель к результату
Вместо 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)
в своем коде, и он должен работать нормально.