Почему число с плавающей запятой в SQL отличается от числа с плавающей запятой в C#

StackOverflow https://stackoverflow.com/questions/122523

Вопрос

Привет, у меня есть 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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top