Подтвердить что ты не робот

Почему -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, это показывает, что закон тождества сохраняется.

4b9b3361

Ответ 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