Pourquoi un flottant SQL est-il différent d’un flottant C #?

Howdy, j’ai un DataRow tiré 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’atsortingbuer cette valeur à une variable locale (type de données c # float), mais j’obtiens une valeur InvalidCastExecption

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

Maintenant, jouer avec ça, je l’ai fait fonctionner, mais ça n’avait aucun sens et ça ne semblait pas correct.

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

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

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

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

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

Et normalement, vous ne voudriez 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 qu’il introduira des erreurs de calcul. Utilisez plutôt un type de données décimal si vous avez besoin de précision.

Je pense que la question principale a été répondue ici, mais je me sens obligé d’append quelque chose pour la partie de la question qui indique que cela fonctionne.

_AccelLimit = (float) (double) exercice [“DefaultAccelLimit”];

La raison pour laquelle cela “fonctionne” et la raison pour laquelle il “ne se sent pas bien” est que vous êtes en train de réduire le double à un flottant par la seconde dissortingbution (celle de gauche). est ok pour tronquer la valeur retournée.

En des mots, cette ligne indique … Récupère un object (ce qui arrive à tenir un double dans ce cas-ci) Lance l’object dans un double (perd tout l’emballage de l’object) Lance le double dans un flotteur (perd toute la précision de un double)

Par exemple, si la valeur est 0.0124022806089461 et que vous faites ci-dessus, la valeur de AccelLimit sera 0.01240228

comme 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 à peu près sûr que c’est une troncature plutôt qu’un arrondi, mais quelqu’un voudra peut-être le confirmer car je n’en suis pas certain.

La raison pour laquelle il ne se sent pas bien est que C # utilise la même syntaxe pour unboxing et pour le casting , qui sont deux choses très différentes. exercise["DefaultAccelLimit"] contient une valeur double, encadrée en tant qu’object. (double) est nécessaire pour rouvrir l’object dans un double. Le (float) en face de cela jette alors le double à une valeur flottante. C # n’autorise 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 la dissortingbution est non destructive. Si un flottant était encadré en tant qu’object que vous vouliez convertir en double, vous le feriez comme ceci: (double)(float)object_var .