Почему число с плавающей запятой в SQL отличается от числа с плавающей запятой в C#
Вопрос
Привет, у меня есть DataRow, извлеченный из DataTable из DataSet.Я обращаюсь к столбцу, который определен в SQL как тип данных с плавающей запятой.Я пытаюсь присвоить это значение локальной переменной (тип данных С# с плавающей запятой), но получаю InvalidCastExecption
DataRow exercise = _exerciseDataSet.Exercise.FindByExerciseID(65);
_AccelLimit = (float)exercise["DefaultAccelLimit"];
Теперь, поигравшись с этим, я заставил это работать, но это не имело никакого смысла и казалось неправильным.
_AccelLimit = (float)(double)exercise["DefaultAccelLimit"];
Может ли кто-нибудь объяснить, чего мне здесь не хватает?
Решение
SQL-число с плавающей запятой является двойным в соответствии с документация для SQLDbType.
Другие советы
Число с плавающей запятой в SQL — это Двойной в CLR (C#/VB).Есть таблица типов данных SQL с эквивалентами CLR на MSDN.
И обычно вы никогда не захотите использовать число с плавающей запятой в SQL Server (или реальное), если вы планируете выполнять математические вычисления с данными, поскольку это неточный тип данных, и он приведет к ошибкам вычислений.Вместо этого используйте десятичный тип данных, если вам нужна точность.
Число с плавающей запятой в Microsoft SQL Server эквивалентно двойному значению в C#.Причина этого в том, что число с плавающей запятой может приближаться только к десятичному числу. точность числа с плавающей запятой определяет, насколько точно это число приближает десятичное число.Тип Double представляет 64-битное число с плавающей запятой двойной точности со значениями в диапазоне от отрицательного 1,79769313486232e308 до положительного 1,79769313486232e308, а также положительный или отрицательный ноль, PositiveInfinity, NegativeInfinity и Not-a-Number (NaN).
Я думаю, что здесь дан ответ на основной вопрос, но я чувствую себя обязанным добавить что-нибудь в тот раздел вопроса, в котором говорится, что это работает.
_AccelLimit = (float)(double)exercision["DefaultAccelLimit"];
Причина, по которой это «работает» и причина, по которой это «не кажется правильным», заключается в том, что вы понижаете двойное значение до числа с плавающей запятой вторым приведением (тот, что слева), поэтому вы теряете точность и фактически сообщаете компилятору, что это можно усечь возвращаемое значение.
На словах в этой строке говорится...Получите объект (который в данном случае удерживает двойник). Вставьте объект в двойную (потеря всей обертывания объекта). Подайте двойник в поплавок (потеря всей тонкой точности двойного)
напримерЕсли значение, скажем, 0,0124022806089461, и вы делаете вышеуказанное, то значение Accellimit будет 0,01240228
поскольку это степень того, что число с плавающей запятой в С# может получить из значения double.Это опасно, и я почти уверен, что это тоже усечение, а не округление, но кто-то, возможно, захочет это подтвердить, поскольку я не уверен.
Причина, по которой это «не кажется правильным», заключается в том, что C# использует тот же синтаксис для распаковка и для Кастинг, это две совершенно разные вещи. exercise["DefaultAccelLimit"]
содержит двойное значение, упакованное как объект. (double)
требуется, чтобы распаковать объект обратно в двойной.А (float)
перед этим тогда бросает двойное значение с плавающей запятой.C# не позволяет выполнять упаковку и приведение в одной и той же операции, поэтому необходимо распаковать, а затем выполнить приведение.
То же самое верно, даже если гипс неразрушающий.Если бы число с плавающей запятой было помещено в коробку как объект, который вы хотели преобразовать в двойной, вы бы сделали это следующим образом: (double)(float)object_var
.