type - Почему C#допускает*неявное*преобразование из Long в Float, когда это может потерять точность?



c# short unsigned int (4)

  1. Что касается целочисленных типов, что подразумевается под «точностью» и «величиной». Разве число n полностью не отличается от числа n + 1 в отличие от действительных чисел, где 3.333333 и 3.333329 можно считать достаточно близкими для вычисления (т.е. в зависимости от того, чего хочет программист точности)

«Точность» определяет количество цифр, которые может нести число. Один байт может содержать только 2 десятичных цифры, если вы (для простоты) кодируете их в BCD. Допустим, у вас есть 2 доступных байта. Вы можете использовать их для кодирования чисел 0-9999 в целочисленном формате или определить формат, в котором последняя цифра означает десятичную степень.

Затем вы можете закодировать 0-999 * (10 ^ 0 - 10 ^ 9)

Вместо кодирования чисел от 0 до 9999 вы можете теперь кодировать числа до 999 000 000 000. Но если вы преобразуете 9999 из целочисленного формата в новый, вы получите только 9990. Вы получили диапазон возможных чисел (ваш величина), но вы потеряли точность.

С doubles и float у вас есть следующие значения, которые могут быть точно представлены: (int = 32 бита, long = 64 бита, оба подписаны :)

int -> float -2 ^ 24 - 2 ^ 24

int -> удвоить все значения

long -> float -2 ^ 24 - 2 ^ 24

длинный -> двойной -2 ^ 53 - 2 ^ 53

Не позволяет неявное преобразование из long в плавающее приглашение к скрытым ошибкам, поскольку это> может привести к тому, что long 'тихо' потеряет значение (как программист C # я привык к компилятору> отлично справляюсь с защитой от таких проблем)

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

Одна такая ошибка: ракета Ариан ...

Похожий вопрос Long in Float, почему? здесь не отвечает то, что я ищу.

Стандарт C # позволяет неявное преобразование из long в float. Но любое значение больше 2 ^ 24, представленное как число с плавающей точкой, неизбежно теряет свою «ценность». Стандарт C # четко гласит, что конвертирование длинных чисел может потерять «точность», но никогда не потеряет «величину».

Мои вопросы
  1. Что касается целочисленных типов, что подразумевается под «точностью» и «величиной». Разве число n полностью не отличается от числа n + 1 в отличие от действительных чисел, где 3.333333 и 3.333329 можно считать достаточно близкими для вычисления (т.е. в зависимости от того, чего хочет программист точности)
  2. Не позволяет неявное преобразование из long в плавающее приглашение к скрытым ошибкам, поскольку это может привести к тому, что long «тихо» потеряет ценность (как программист C # я привык к тому, что компилятор отлично справляется с защитой от таких проблем)

Так что же могло послужить основанием для команды разработчиков языка C #, чтобы это преобразование было неявным? Что я здесь упускаю, что оправдывает неявное преобразование из long в float?


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


Максимальное long значение может быть помещено в число с float как

float.MaxValue ~= 3.402823+e38 
long.MaxValue ~= 9.223372+e18 

хотя long это 64bit Integer тип 64bit Integer а float 32bit , но компьютер обрабатывает float's иначе, чем long's . Но для float большая дальность достигается за счет точности.

long имеет гораздо более высокую точность, чем float но float имеет более высокий порядок 10 ^ 38 по сравнению с long 10 ^ 18.

Я не думаю, что они допустили ошибку, позволив неявное преобразование из long в float как float по-прежнему точен до 7 цифр. Поэтому, если кому-то нужна большая точность, он всегда может использовать double или десятичное число.

Double -15-16 цифр (64 бит)

Decimal -28-29 значащих цифр (128 бит)


Это хороший вопрос. На самом деле вы можете обобщить этот вопрос, поскольку такая же проблема существует для неявных преобразований:

  • int float
  • uint на float
  • long floatчем ты спрашиваешь )
  • ulong float
  • long double
  • ulong чтобы double .

Фактически, все целочисленные типы (и даже char !!) имеют неявное преобразование в float и double ; однако только перечисленные выше преобразования приводят к потере точности. Еще одна интересная вещь, которую стоит отметить, заключается в том, что спецификация языка C # имеет противоречивый аргумент при объяснении «почему не существует неявного преобразования из десятичного числа в двойное»:

Десятичный тип имеет большую точность, но меньший диапазон, чем типы с плавающей точкой. Таким образом, преобразования из типов с плавающей точкой в ​​десятичные могут вызвать исключения переполнения, а преобразования из десятичных в типы с плавающей точкой могут привести к потере точности. По этим причинам не существует неявных преобразований между типами с плавающей запятой и десятичными , и без явного приведения невозможно смешивать десятичные операнды с плавающей точкой в ​​одном выражении.

Я думаю, что на вопрос «почему было принято это решение» лучше всего может ответить кто-то вроде Эрика Липперта. Моя догадка ... это одна из тех вещей, где разработчики языка не имеют никаких сильных аргументов в пользу идти в одну сторону или другую сторону, поэтому они выбрали (как они думали), тем лучше альтернатив, хотя это спорно , В свою защиту, когда вы конвертируете большой float long в float , вы теряете точность, но вы по-прежнему получаете лучшее представление этого числа в мире с плавающей запятой. Это не что иное, как преобразование, скажем, int в byte где может произойти переполнение (возможно, целочисленное значение находится за пределами того, что может представлять byte ), и вы получите несвязанное / неправильное число. Но все же, на мой взгляд, было бы более согласованно не иметь неявных преобразований из decimal в плавающей запятой, если бы они не имели этих других преобразований, которые вызывают потерю точности.





implicit-conversion