Почему приведение большого двойного значения в sbyte возвращает 0 в C#? - PullRequest
0 голосов
/ 15 января 2020

Я на самом деле проверяю поведение приведения в C# в непроверенном контексте. Как сказано в документации, в непроверенном контексте приведение всегда выполняется успешно. Но иногда, в отдельных случаях, приведение от одного указанного типа c к другому типу дает неожиданный результат.

Например, я протестировал три приведения типа "double to sbyte":

var firstCast = (sbyte) -129.83297462979882752;          // Result : 127.
var secondCast = (sbyte) -65324678217.74282742874973267; // Result : 0.
var thirdCast = (sbyte) -65324678216.74282742874973267;  // Result : 0.

Просто чтобы прояснить, разница между вторым и третьим дублем составляет всего 1 (secondDouble - firstDouble = 1). В этом случае результаты приведения, похоже, всегда равны 0 для любого "большого" двойного значения.

Мой вопрос: почему второе и третье приведение приводят к 0? Я искал ответ в документации C#, но я не нашел ни одного.

Я протестировал вышеуказанное с помощью. Net Framework 4.7.2.

1 Ответ

3 голосов
/ 15 января 2020

В соответствии со спецификацией языка C# ,

Для преобразования с плавающим или двойным типом в целочисленный тип обработка зависит от контекста проверки переполнения, в котором происходит преобразование:

Без использования операторов checked или unchecked по умолчанию контекст проверки переполнения не проверяется, поэтому мы рассмотрим:

В В непроверенном контексте преобразование всегда завершается успешно и выполняется следующим образом.

  • Если значение операнда равно NaN или бесконечно, результатом преобразования является неопределенное значение типа назначения.

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

  • В противном случае результатом преобразования является неопределенное значение типа назначения.

Здесь значения не являются ни NaN, ни бесконечными. При округлении до нуля они не находятся в допустимом диапазоне sbyte, который составляет от -128 до 127, поэтому применяется последняя точка маркера, что означает, что результат такого приведения не определен.

In Другими словами, результат этого приведения зависит от того, какой компилятор вы используете. Разные компиляторы могут делать разные вещи, и они все равно будут называться C# компиляторами. Вполне вероятно, что любой используемый вами компилятор просто подумал, что было бы лучше вернуть 0 для преобразования, если значение для преобразования находится очень далеко от нижней / верхней границы.

...