Я понимаю, что это связано с тем, как процессоры обрабатывают переполнения, но я не вижу его. Умножение с разными отрицательными значениями дает либо нуль, либо -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
, это показывает, что закон тождества сохраняется.