TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.74K subscribers
Post #3269 1.62K
День 2728. #ЗаметкиНаПолях
Сравнение Чисел в .NET
Когда люди сравнивают числа, они обычно ожидают, что равенство означает одинаковые значения. Для чисел с плавающей точкой (Half, float и double) в .NET существуют два понятия равенства:
1. Семантика сравнения IEEE, используемая оператором ==,
2. Семантика эквивалентности для объектов .NET, используемая методом Equals.

На первый взгляд это выглядит противоречиво. На практике каждый из них решает свою проблему.

Краткое сравнение
Для чисел Half, double и float важны следующие крайние случаи:
1. NaN и NaN
- == = false
- Equals = true
- CompareTo = 0

2. +0.0 и -0.0
- == = true
- Equals = true
- CompareTo = 0

3. +Infinity и +Infinity
- == = true
- Equals = true
- CompareTo = 0

4. -Infinity и +Infinity
- == = false
- Equals = false
- CompareTo < 0

5. NaN и конечное число
- == = false, a != = true
- Equals = false
- NaN.CompareTo(x) < 0

Оператор == соответствует правилам сравнения чисел с плавающей запятой из IEEE 754 / IEC 60559. Equals разработан для поддержки контрактов равенства .NET, используемых коллекциями и словарями.

Почему NaN == NaN ложно, а NaN.Equals(NaN) истинно?
NaN означает «Не число». Это специальное значение IEEE 754, используемое, когда операция не определена, например, деление на 0 (0.0 / 0.0).

IEEE 754 рассматривает NaN как неупорядоченное значение при сравнениях, т.е.:
- x == y ложно, если хотя бы одна сторона NaN;
- x < y, x > y, x <= y, x >= y ложно, если хотя бы одна сторона NaN;
- x != y истинно, если хотя бы одна сторона NaN;
Таким образом:
double x = double.NaN;

Console.WriteLine(x == x); // False
Console.WriteLine(x != x); // True
Console.WriteLine(x < 0); // False
Console.WriteLine(x >= 0); // False


Чтобы проверить, что значение является NaN, используйте API типа:
Half h = Half.NaN;
float f = float.NaN;
double d = double.NaN;

Console.WriteLine(Half.IsNaN(h)); // True
Console.WriteLine(float.IsNaN(f)); // True
Console.WriteLine(double.IsNaN(d)); // True

Но .NET также нуждается в понятии равенства, которое работает с контейнерами на основе хэшей. Если бы оператор Equals соответствовал стилю IEEE для NaN, это нарушило бы рефлексивность (x.Equals(x) должно быть true), и ключи, содержащие NaN, вели бы себя некорректно в словарях/хэшсетах. Поэтому Half.Equals, Double.Equals и Single.Equals обрабатывают NaN особым образом и возвращают true, когда оба значения являются NaN.

Окончание следует…

Источник:
https://www.meziantou.net/number-comparison-in-dotnet-equals-and-ieee-754-edge-cases.htm
  • 👍 7
More from @netdeveloperdiary
  1. Sep 26, 2026День 2796. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Продолжение Начало Три…
  2. Sep 25, 2026День 2795. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Начало Проблема с позиц…
  3. Sep 24, 2026День 2794. #Оффтоп #Здоровье Сегодня будет необычный пост. Завтра в Москве стартует конфер…
  4. Sep 23, 2026День 2793. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
  5. Sep 22, 2026День 2792. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
  6. Sep 21, 2026🔍Тестовое собеседование с Senior C# разработчиком уже завтра 22 сентября(уже завтра!) в 1…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →