Отрицательный ноль связан с тем, как число хранится в двоичном виде, а не с каким-либо реальным достижимым результатом математического вычисления.
В памяти с плавающей запятой, самый верхний бит часто используется для обозначения знака. Это оставляет 31 бит для данных (в 32-битном значении с плавающей запятой), поэтому фактически есть два представления для нуля.
00000000 00000000 00000000 00000000
Или
00000000 00000000 00000000 00000001
Оба представляют ноль, но один со знаком бит установлен в отрицательное значение.
Естественно, это обычно происходит, когда вы увеличиваете максимально возможное положительное число, оно переполняется обратно до отрицательного нуля.
В .net, однако, я думаю, что по умолчанию тип выполняет проверки переполнения и генерирует исключение, а не позволяет вам переполниться, поэтому единственный способ действительно архивировать это значение - установить его напрямую. Кроме того, -0 всегда должен сравниваться равным + 0.
Есть больше об этом на Wikipeida