#c# #.net #type-conversion
#c# #.net #тип-преобразование
Вопрос:
Я пытаюсь преобразовать double в Int64 и получаю какое-то странное поведение. Чтобы проверить свою проблему, я попробовал следующий код:
double temporary = Int64.MaxValue;
Int64 tem = Convert.ToInt64(temporary);
Я все еще получаю исключение переполнения при преобразовании double в Int64. Это ошибка? Или есть что-то, чего я не понимаю?
Комментарии:
1. В какой строке вы получаете исключение? Может ли проблема быть в первой строке, а не во второй?
2. В double может храниться 15 значащих цифр. Значение Int64.Max состоит из 19 цифр. Таким образом, double содержит только приближение MaxValue. Он округлился, бабах, когда вы пытаетесь вернуться назад. Никогда не пишите подобный код.
3. Не мог бы отладить это самостоятельно? Просто посмотрите на значение в
temporary
, и вы увидите, что оно больше максимального значенияInt64
. В документации дляConvert.ToInt64
конкретно говорится, что произойдет исключение переполнения. Пожалуйста, прочитайте документацию в следующий раз.4. @tnw отладчик удалил две цифры (08 не было видно) и ввел научную запись. Я уверен, что есть способы настроить отладчик, но это было намного быстрее.
Ответ №1:
Суть этого в том, что не все действительные числа могут быть представлены конечными типами данных с плавающей запятой. В частности, существуют 64-разрядные целочисленные значения, которые не имеют точного представления в виде значений с плавающей запятой двойной точности.
Значение Int64.MaxValue
равно 9,223,372,036,854,775,807
. Ближайшим значением двойной точности к этому является 9,223,372,036,854,775,808
. Итак, когда
double temporary = Int64.MaxValue;
выполняется, значение, присвоенное temporary
фактически 9,223,372,036,854,775,808.0
.
При попытке преобразовать это значение двойной точности в Int64
происходит переполнение, поскольку значение превышает Int64.MaxValue
.
Комментарии:
1. Мне здесь любопытно. Если я попытаюсь
temporary = temporary - 1;
, все равно возникнет исключение.2. @Steve Конечно. Это потому, что
temporary - 1 == temporary
😉 Подумайте об этом.3. @Steve Тогда попробуйте и убедитесь сами. Это займет у вас всего несколько секунд.
4. @DavidHeffernan Спасибо за ответ. Ссылка очень помогла. Я должен использовать 9,223,372,036,854,775,295 вместо фактического максимума.
5. Да, значения так далеко разнесены!
Ответ №2:
A double
не может точно представлять Int64.MaxValue
, поэтому оно округляется в большую сторону. Поскольку long
не может представлять округленное значение, вы получаете исключение.