Почему плавающий SQL отличается от плавающего C # - PullRequest
41 голосов
/ 23 сентября 2008

Привет, у меня есть DataRow из DataTable из DataSet. Я обращаюсь к столбцу, который определен в SQL как тип данных с плавающей точкой. Я пытаюсь присвоить это значение локальной переменной (тип данных c # float), но получаю InvalidCastExecption

DataRow exercise = _exerciseDataSet.Exercise.FindByExerciseID(65);
_AccelLimit = (float)exercise["DefaultAccelLimit"];  

Теперь, играя с этим, я заставил это работать, но это не имело никакого смысла, и это не чувствовало себя правильным.

_AccelLimit = (float)(double)exercise["DefaultAccelLimit"];

Кто-нибудь может объяснить, чего мне здесь не хватает?

Ответы [ 6 ]

71 голосов
/ 23 сентября 2008

Число с плавающей запятой SQL является двойным в соответствии с документацией для SQLDbType .

24 голосов
/ 23 сентября 2008

Число с плавающей запятой в SQL это Double в CLR (C # / VB) В MSDN есть таблица типов данных SQL с эквивалентами CLR .

3 голосов
/ 23 сентября 2008

И обычно вы никогда не захотите использовать float в SQL Server (или в реальном), если вы планируете выполнять математические вычисления над данными, так как это неточный тип данных, и это приведет к ошибкам вычисления. Вместо этого используйте десятичный тип данных, если вам нужна точность.

2 голосов
/ 23 сентября 2008

Число с плавающей запятой в Microsoft SQL Server эквивалентно Double в C #. Причина этого заключается в том, что число с плавающей запятой может приближаться только к десятичному числу, точность числа с плавающей запятой определяет, насколько точно это число приближается к десятичному числу. Тип Double представляет 64-разрядное число с плавающей запятой двойной точности со значениями в диапазоне от отрицательного 1.79769313486232e308 до положительного 1.79769313486232e308, а также от положительного или отрицательного нуля, PositiveInfinity, NegativeInfinity и Not-a-Number (NaN).

0 голосов
/ 14 октября 2015

Причина, по которой он "не чувствует себя хорошо", заключается в том, что C # использует один и тот же синтаксис для распаковки и для приведения , что является двумя совершенно разными вещами. exercise["DefaultAccelLimit"] содержит двойное значение, упакованное как объект. (double) требуется для распаковки объекта обратно в double. (float) перед этим, тогда приводит к двойному значению с плавающей точкой. C # не разрешает боксировать и кастовать в одной и той же операции, поэтому вы должны распаковать, а затем кастовать.

То же самое верно, даже если приведение не является разрушительным. Если бы float был упакован как объект, который вы хотели бы привести к двойному результату, вы бы сделали это так: (double)(float)object_var.

0 голосов
/ 08 октября 2015

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

_AccelLimit = (float) (double) упражнение ["DefaultAccelLimit"];

Причина, по которой это «работает», и причина, по которой он «не чувствует себя правильным», заключается в том, что вы понижаете удвоение до числа с плавающей точкой со второго броска (тот, что слева), так что вы теряете точность и эффективно говорите компилятор, что можно усечь возвращенное значение.

На словах эта строка гласит ... Получить объект (в данном случае он содержит двойное число) Приведите объект в удвоение (теряя всю обертку объекта) Бросьте двойное число в число с плавающей точкой (потеря точной точности двойного)

например. Если значение сказать 0,0124022806089461 и вы делаете выше, то значение AccelLimit будет 0.01240228

так как это степень того, что float в c # может получить из значения double. Это опасная вещь, и я почти уверен, что это тоже усечение, а не округление, но кто-то может захотеть подтвердить это, поскольку я не уверен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...