Как получить результат -0 в вычислениях с плавающей запятой и отличить его от +0 в C#?

в документации MSDN упоминается, что double тип включает в себя отрицательный нуль. Однако, оба -1.0 / double.PositiveInfinity и -double.Epsilon / 2 Кажется, что возвращает нормальный 0 (и сравнивает равным ему). Как я могу получить -0?

5 ответов


вот практический пример дифференцирования между ними без изучения битов. Ссылки на MSDN здесь и здесь помог мне в построении этого примера.

static void Main(string[] args)
{
    float a = 5 / float.NegativeInfinity;
    float b = 5 / float.PositiveInfinity;
    float c = 1 / a;
    float d = 1 / b;
    Console.WriteLine(a);
    Console.WriteLine(b);
    Console.WriteLine(c);
    Console.WriteLine(d);
}

выход:

0
0
-Infinity
Infinity

обратите внимание, что -0 и 0 выглядят одинаково для сравнения, вывода и т. д. Но если вы разделите 1 на них, вы получите-бесконечность или бесконечность, в зависимости от того, какой ноль у вас есть.


отрицательный ноль связан с тем, как число хранится в двоичном формате, а не какой-либо реальный достижимый результат математического расчета.

в хранилище с плавающей запятой самый верхний бит часто используется для обозначения знака. Это оставляет 31 бит для данных (в 32-битном значении с плавающей запятой), поэтому на самом деле существует два представления для нуля.

00000000 00000000 00000000 00000000
Или
00000000 00000000 00000000 00000001

оба представляют ноль, но один со знаком "минус".

естественно, это обычно происходит, когда вы увеличиваете максимально возможное положительное число, оно будет переполняться до отрицательного нуля.

в .net, однако я думаю, что по умолчанию тип проверяет переполнение и выдает исключение, а не позволяет переполнять, поэтому единственный способ действительно архивировать это значение-установить его напрямую. Кроме того, -0 всегда должен сравниваться равным +0.

больше об этом на Wikipeida


один из способов-использовать BitConverter.Метод getbytes. Если вы проверите байты, вы увидите, что бит знака для значения фактически установлен, указывая, что его отрицательный.

byte[] zeroBytes = BitConverter.GetBytes(zero);
byte[] negZeroBytes = BitConverter.GetBytes(negZero);

bool sameBytes = zeroBytes[7] == negZeroBytes[7];

попробуйте это. Если pz является положительным нулем и nz отрицательный ноль:

Double.PositiveInfinity/pz => Double.PositiveInfinity
Double.PositiveInfinity/nz => Double.NegativeInfinity

получил от спецификация ECMA C#.

вы можете получить отрицательный ноль, разделив любое положительное число на отрицательную бесконечность:

10.0/Double.NegativeInfinity

после проверки я вижу, что -1.0 / double.PositiveInfinity тут вернуться -0. Действительно,1.0 / (-1.0 / double.PositiveInfinity) возвращает -infinity.