Почему -1L * -9223372036854775808L == -9223372036854775808L
Я понимаю, что это связано с тем, как процессоры обрабатывают переполнения, но я не вижу его. Умножение с разными отрицательными значениями дает либо нуль, либо -2^63
:
В С# Interactive:
> return unchecked (-1L * -9223372036854775808L);
-9223372036854775808
> return unchecked (-2L * -9223372036854775808L);
0
> return unchecked (-3L * -9223372036854775808L);
-9223372036854775808
> return unchecked (-4L * -9223372036854775808L);
0
> return unchecked (-5L * -9223372036854775808L);
-9223372036854775808
В F # Interactive:
> -1L * -9223372036854775808L;;
val it : int64 = -9223372036854775808L
> -2L * -9223372036854775808L;;
val it : int64 = 0L
> -3L * -9223372036854775808L;;
val it : int64 = -9223372036854775808L
> -4L * -9223372036854775808L;;
val it : int64 = 0L
Я пришел к этому, потому что удивил меня в F #, пока не понял, что F # по умолчанию работает в неконтролируемых контекстах. Тем не менее, я не мог легко объяснить поведение.
Я понимаю, почему 9223372036854775807L + 1L == -9223372036854775808L
я просто не получаю его для умножения с отрицательным числом и почему он чередуется между 0
(двоичный все нули) и -2^63
(двоичный самый старший бит 1, остальные ноль).
Интересно, что это справедливо с правило мультипликативной идентичности, т.е. с -1L * -9223372036854775808L == -9223372036854775808L
следует, что -1L * -1L * -9223372036854775808L == -9223372036854775808L
и так как -1L * -1L = 1L
, это показывает, что закон тождества сохраняется.
Ответы
Ответ 1
Ответы, которые вы получаете, верны по модулю 2 ^ 64: то есть они отличаются от математически правильных ответов кратностью 2 ^ 64 и разумным определением правильно усеченного ответа.
Я буду использовать & cong; связать два числа, которые конгруэнтны по модулю 2 ^ 64. Таким образом,
- -1 * -2 ^ 63 = 2 ^ 63 & cong; -2 ^ 63
- -2 * -2 ^ 63 = 2 ^ 64 & cong; 0
- -3 * -2 ^ 63 = 3 * 2 ^ 63 = 2 ^ 64 + 2 ^ 63 & cong; -2 ^ 63
и т.д. Заметим, что 2 ^ 63 и -2 ^ 63 конгруэнтны, но это -2 ^ 63, которое представимо в соответствии с условностями арифметики с двумя дополнениями.
Ответ 2
Поведение ожидается из-за того, как отрицательные числа представлены в 2 дополнениях.
Теперь предположим, что у вас 8 бит.
1000 0000
Это -128
(подпись). его можно также перевести на 128
(без знака)
Умножение на -1
будет таким, как
1000 0000 (*1)=> 1000 0000 (negate)=> 0111 1111 (+1)=> 1000 0000
Что в 8 бит переполняется, и вы снова получаете -128
. (о, и не забывайте, что максимальное значение, которое вы можете получить здесь, 127
не 128
, потому что MSB используется для знака)
Умножение на -2
будет таким, как
1000 0000 (*2)=> 1 0000 0000 (negate)=> 1111 1111 (+1)=> 1 0000 0000
И поскольку это значение в 8-битных переполнениях, вы получаете 0