web-dev-qa-db-fra.com

Pourquoi un float SQL est-il différent d'un float C #?

Howdy, j'ai un DataRow extrait d'un DataTable à partir d'un DataSet. J'accède à une colonne définie dans SQL en tant que type de données float. J'essaie d'assigner cette valeur à une variable locale (type de données c # float) mais j'obtiens un InvalidCastExecption 

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

Maintenant, en jouant avec ça, je le faisais marcher, mais cela n’avait aucun sens et cela ne me semblait pas juste. 

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

Quelqu'un peut-il expliquer ce qui me manque ici?

40
Keith Sirmons

Un float SQL est un double selon la documentation de SQLDbType .

69
Austin Salonen

Un float en SQL est un Double dans le CLR (C #/VB). Il y a une table de types de données SQL avec les équivalents CLR sur MSDN.

24
bdukes

Et normalement, vous ne voudrez jamais utiliser float dans SQL Server (ou réel) si vous prévoyez d'effectuer des calculs mathématiques sur les données, car il s'agit d'un type de données inexact et cela entraînera des erreurs de calcul. Utilisez plutôt un type de données décimal si vous avez besoin de précision.

3
HLGEM

Le flottant dans Microsoft SQL Server équivaut à un double en C #. La raison en est qu’un nombre à virgule flottante ne peut se rapprocher que d’un nombre décimal, le précision d’un nombre à virgule flottante détermine la précision avec laquelle ce nombre se rapproche d’un nombre décimal. Le type Double représente un nombre à virgule flottante double précision de 64 bits avec des valeurs allant de négatif 1,79769313486232e308 à 1,79769313486232e308 positif, ainsi que des valeurs zéro ou positif, PositiveInfinity, NegativeInfinity et Not-a-Number (NaN). 

2
pdavis

La raison pour laquelle "il ne se sent pas bien" est que C # utilise la même syntaxe pour unboxing et pour casting, qui sont deux choses très différentes. exercise["DefaultAccelLimit"] contient une double valeur, encadrée en tant qu'objet. (double) est requis pour unbox l'objet dans un double. Le (float) devant celui-ci puis jette le double sur une valeur float. C # n'autorisant pas la boxe et le casting dans la même opération, vous devez donc déballer, puis lancer.

La même chose est vraie même si le casting est non destructif. Si un float était encadré en tant qu'objet que vous vouliez transformer en double, vous le feriez comme suit: (double)(float)object_var.

0
dubrowgn

Je pense que la question principale a reçu une réponse ici, mais je me sens obligé d'ajouter quelque chose à la partie de la question qui dit que cela fonctionne.

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

La raison pour laquelle cela "fonctionne" et "ne se sent pas bien" est que vous rétrogradez le double en float par la deuxième distribution (celle de gauche), de sorte que vous perdez de la précision et que vous dites efficacement au compilateur est ok pour tronquer la valeur retournée.

En mots, cette ligne indique: ... Obtenez un objet (dans ce cas, un double) .__ Transformez l'objet en un double (perd tout l'enveloppe) .__ Transformez le double en un float (perdant toute la précision d'un double)

par exemple. Si la valeur est disons 0.0124022806089461 Et que vous faites ce qui précède, la valeur de AccelLimit sera alors 0.01240228

car c’est l’étendue de ce qu’un flottant dans c # peut obtenir de la valeur double . C’est une chose dangereuse à faire et je suis presque sûr que c’est aussi une troncature plutôt que de l’arrondir, mais il se peut que quelqu'un veuille confirmer cela, pas certain.

0
David Bridge