Я неправильно делаю модуль? Потому что в Java -13 % 64
предполагается оценивать, -13
но я получаю 51
.
%
является оператором остатка.
Я неправильно делаю модуль? Потому что в Java -13 % 64
предполагается оценивать, -13
но я получаю 51
.
%
является оператором остатка.
Ответы:
Используются оба определения модуля отрицательных чисел - в некоторых языках используется одно определение, а в некоторых - другое.
Если вы хотите получить отрицательное число для отрицательных входов, вы можете использовать это:
int r = x % n;
if (r > 0 && x < 0)
{
r -= n;
}
Точно так же, если вы использовали язык, который возвращает отрицательное число на отрицательном входе, и вы бы предпочли положительный:
int r = x % n;
if (r < 0)
{
r += n;
}
x % y
, А) , если x
отрицательный остаток отрицательный, то есть x % y == -(-x % y)
. Б) знак y
не действует, т.е.x % y == x % -y
Поскольку "математически" оба верны:
-13 % 64 = -13 (on modulus 64)
-13 % 64 = 51 (on modulus 64)
Разработчики языка Java должны были выбрать один из вариантов, и они выбрали:
знак результата равен знаку дивиденда.
Об этом говорится в спецификациях Java:
https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17.3
-13 % 64 = 51
когда я ожидал -13
?».
int result = (-5) % 3;
дает -2. int result = (-3) % 5;
дает -3. В общем, int result = (-a) % b;
дает правильный ответ, когда | -a | > б. Чтобы получить правильный результат, когда | -a | <b мы должны обернуть делитель. int result = ((-a) % b) + b;
для отрицательного а или int result = (((-a) % b) + b) % b;
для положительного или отрицательного а
Ваш результат неверен для Java. Пожалуйста, опишите контекст, как вы к этому пришли (ваша программа, реализация и версия Java).
15.17.3 Оставшийся оператор%
[...]
Операция остатка для операндов, которые являются целыми числами после двоичного числового продвижения (§5.6.2), производит такое значение результата, что (a / b) * b + (a% b) равно а.
15.17.2 Оператор отдела /
[...]
Целочисленное деление округляет до 0.
Поскольку / округляется в сторону нуля (в результате получается ноль), результат% в этом случае должен быть отрицательным.
int result = (-5) % 3;
дает -2 int result = (-3) % 5;
дает -3 В общем, int result = (-a) % b;
дает правильный ответ, когда | -a | > b Чтобы получить правильный результат, когда | -a | <b мы должны обернуть делитель. int result = ((-a) % b) + b;
для отрицательного a или int result = (((-a) % b) + b) % b;
для положительного или отрицательного a.
(-3) % 5
правильный результат согласно определению равен -3
, и правильная реализация Java должна дать этот результат.
(-3)%5
действительно дает -3
, и если мы хотим получить положительный остаток, мы должны добавить к нему 5, и тогда результат будет2
ты можешь использовать
(x % n) - (x < 0 ? n : 0);
((x % k) + k) % k
. (Хотя ваш, вероятно, более читабельный.)
[0, sign(divisor) * divisor)
вместо [0, sign(dividend) * divisor)
.
Ваш ответ находится в Википедии: операция по модулю
В нем говорится, что в Java знак операции по модулю такой же, как у делимого. и поскольку мы говорим об остальной части операции деления, это нормально, что она возвращает -13 в вашем случае, поскольку -13/64 = 0. -13-0 = -13.
РЕДАКТИРОВАТЬ: Извините, неправильно понял ваш вопрос ... Вы правы, java должна дать -13. Можете ли вы предоставить больше окружающего кода?
Арифметика по модулю с отрицательными операндами определяется разработчиком языка, который может оставить это языковой реализации, которая может передать определение архитектуре ЦП.
Мне не удалось найти определение языка Java.
Спасибо, Иштар, Спецификация языка Java для оператора остатка% говорит, что знак результата такой же, как знак числителя.
Чтобы преодолеть это, вы можете добавить 64
(или какова ваша база модуля) к отрицательному значению, пока оно не станет положительным.
int k = -13;
int modbase = 64;
while (k < 0) {
k += modbase;
}
int result = k % modbase;
Результат все равно будет в том же классе эквивалентности.
x = x + m = x - m
по модулю m
.
так -13 = -13 + 64
по модулю 64
и -13 = 51
по модулю 64
.
Допустим Z = X * d + r
, если 0 < r < X
тогда делением Z/X
назовем r
остаток.
Z % X
возвращает остаток Z/X
.
Функция mod определяется как величина, на которую число превышает наибольшее целое кратное делителя, не превышающее это число. Итак, в вашем случае
-13 % 64
наибольшее целое число, кратное 64, которое не превышает -13, равно -64. Теперь, когда вы вычитаете -13 из -64, получается 51-13 - (-64) = -13 + 64 = 51
В моей версии Java JDK 1.8.0_05 -13% 64 = -13
вы можете попробовать -13- (int (-13/64)), другими словами, деление приведено к целому числу, чтобы избавиться от дробной части, а затем вычесть ее из числителя. Итак, numerator- (int (числитель / знаменатель)) должен дать правильный остаток и подпись
В последних версиях Java вы получаете -13%64 = -13
. Ответ всегда будет иметь знак числителя.
Согласно разделу 15.17.3 JLS, «операция с остатком для операндов, которые являются целыми числами после двоичного числового продвижения, выдает такое значение результата, что (a / b) * b + (a% b) равно a. Это тождество сохраняется даже в особом случае, когда дивиденд - это отрицательное целое число максимально возможной величины для данного типа, а делитель равен -1 (остаток равен 0) ».
Надеюсь, это поможет.
Я не думаю, что Java в этом случае возвращает 51. Я запускаю Java 8 на Mac и получаю:
-13 % 64 = -13
Программа:
public class Test {
public static void main(String[] args) {
int i = -13;
int j = 64;
System.out.println(i % j);
}
}