Как преобразовать из double в Int64

#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 не может представлять округленное значение, вы получаете исключение.