Похоже, вы ищете крайние случаи, когда они не являются взаимозаменяемыми, поэтому вот несколько примеров.
object.Equals
на struct
с
> struct SomeStruct { public double X; }
> var a = new SomeStruct { X = 0d };
> var b = new SomeStruct { X = -0d };
> a.Equals(b)
false
>
Инверсия
> 1/0d
∞
> 1/-0d
-∞
>
Явное преобразование байтов
Любой тип явной побитовой или побитовой деконструкции, конечно, или тип Punning.Эти примеры с ПК:
> BitConverter.GetBytes(0d)
byte[8] { 0, 0, 0, 0, 0, 0, 0, 0 }
> BitConverter.GetBytes(-0d)
byte[8] { 0, 0, 0, 0, 0, 0, 0, 128 }
>
Math.Sign
Несмотря на то, что вы можете ожидать, Math.Sign
не не различает отрицательный и положительный ноль.Он только сообщает вам, равно ли число, больше или меньше 0.
> Math.Sign(-0f)
0
Math.Min
и Math.Max
Некоторые арифметические операции имеют крайние случаи для -0.Один интересный - Math.Min
(и эквивалентно для max), который заключается в том, что при сравнении нулей со знаком он возвращает второй.Итак:
> BitConverter.GetBytes(Math.Min(0.0, -0.0))
byte[8] { 0, 0, 0, 0, 0, 0, 0, 128 }
> BitConverter.GetBytes(Math.Min(-0.0, 0.0))
byte[8] { 0, 0, 0, 0, 0, 0, 0, 0 }
>
Примечание о нерегулярных decimal
представлениях
Тип decimal
как таковой не имеет отрицательного 0 как такового, но у него есть несколько двоичных представлений для нуля:
> new decimal(new int[4] { 0, 0, 0, 0 })
0
> new decimal(new int[4] { 0, 0, 0, -2147483648 })
0
>
Второй пример можно рассматривать как отрицательный ноль, поскольку он поразрядно идентичен обычному нулю, за исключением установленного бита отрицания.Но для форматера это просто ноль.На самом деле существуют десятки нулевых представлений для decimal
для различных сдвигов десятичной запятой, все они арифметически эквивалентны и отображаются как 0:
> new decimal(new int[4] { 0, 0, 0, 131072 })
0.00
> new decimal(new int[4] { 0, 0, 0, 1835008 })
0.0000000000000000000000000000
> new decimal(new int[4] { 0, 0, 0, 65536 })
0.0
Тем не менее, вы сможете толькоотличать их друг от друга средствами двоичного сравнения или двоичного преобразования.Из экспериментов видно, что вышеприведенный трюк struct
на них не работает.Math.Min
возвращает, какой бы ни был дан ноль в секунду.
Бонус: Субнормальные числа
Определенные комбинации битов в типах float
и double
представляют субнормальные (иначе денормалированные)) ценности.Я не буду вдаваться в то, что они есть - вместо этого посмотрите ссылку - но важно знать, что спецификация CLI явно объявляет их операции как специфичные для реализации.Я не знаю , что существуют платформы, которые рассматривают их как 0, но может быть.С другой стороны, Язык программирования C # говорит, что они "считаются действительными ненулевыми значениями".