10
votes

SQL Server: Calcul avec littéraux numériques

J'ai fait des tests avec des calculs de points flottants pour minimiser la perte de précision. J'ai trébuché sur un phénomène que je veux montrer ici et j'espère avoir une explication.

Quand j'écris xxx

Le résultat est xxx

Lorsque j'écris la même formule et que je fais de la moulage explicite sur float xxx

Le résultat est xxx


Jusqu'à présent, je pensais que les littéraux numériques avec des décimales sont automatiquement traités comme des valeurs flottant avec la précision appropriée. Casting vers Real montre le même résultat que la coulée sur float .

  • Y a-t-il une documentation sur la manière dont SQL Server évalue les littéraux numériques?
  • de quel type de données sont ces littéraux?
  • Dois-je vraiment les jeter à Float Obtenez une meilleure précision (ce qui ressemble à ironie pour moi :)?
  • Y a-t-il un moyen plus facile d'encombrer mes formules avec des moulages?

0 commentaires

4 Réponses :


10
votes

SQL Server utilise le plus petit type de données possible.

Lorsque vous exécutez ce script xxx

Vous verrez que SQL Server a implicitement utilisé un numérique (2, 1). DataType.
La division de 60.0 convertit le résultat en numérique (8, 6).
Le calcul final convertit le résultat en numérique (17, 10).


edit

pris à partir de livres SQL Server en ligne Type de données Conversion

dans les déclarations transactives-SQL, une constante avec un point décimal est automatiquement converti en une valeur de données numérique, en utilisant la précision minimale et l'échelle nécessaire. Par exemple, la constante 12.345 est converti en une valeur numérique avec une précision de 5 et a échelle de 3.


5 commentaires

Ah .. Je ne savais pas cette méthode jusqu'à maintenant. Merci beaucoup :)


Donc, il n'y a aucun moyen d'une extinction explicite pour obtenir le résultat attendu? Y a-t-il une autre façon de dire à SQL Server qu'un littéral donné est de type (par exemple)?


@Vvs, outre une fonte explicite comme vous le faites déjà, pas que je sache. SQL Server interprète toujours la valeur en tant que numérique. Le problème peut être atténué un peu si vous ajoutez une précision à vos valeurs comme 1.000000000000000000000000000000000000.


@Lieven: Avez-vous une sorte de documentation qui confirme votre déclaration selon laquelle "SQL Server interprète toujours la valeur en tant que numérique"?


@VSS: J'ai ajouté une référence à la documentation.



4
votes

Oui, vous devez souvent les lancer pour flotter obtenir une meilleure précision. Mon prise dessus:

Pour de meilleures décimales de précision avant les calculs


1 commentaires

La justification de l'article est défectueuse. Il est basé sur certaines valeurs arbitraires. Il serait facile de trouver un exemple de contre-exemple en faveur du type décimal. Ces revendications indiennes basées sur un exemple empirique sont des pièges en soi.



3
votes

Je pense qu'il faut comprendre ce qui se passe dans les coulisses pour une référence future dans des cas similaires.

Les valeurs numériques littérales avec point décimal excluant la notation scientifique représentent le type de données décimal qui est stocké de type décimal qui est plus petit possible. Même citation que Lieven Keersmaekers de: https://msdn.microsoft.com/fr -US / Bibliothèque / MS191530% 28SQL.90% 29.aspx # _Decimal P>

dans les déclarations de transact-sql, une constante avec un point décimal est transformé automatiquement en une valeur de données numérique à l'aide du minimum précision et échelle nécessaire. Par exemple, la constante 12.345 est converti en une valeur numérique avec une précision de 5 et une échelle de 3. p> BlockQuote>

Les zéros de fuite à droite de point décimal spécifient l'échelle. Les principaux zéros laissés de point décimal sont ignorés. P>

Quelques exemples: p> xxx pré>

Un autre point à considérer est Type de données PRECÉDENCE . Lorsqu'un opérateur combine deux expressions de types de données différents, les règles de la priorité de type de données indiquent que le type de données avec la priorité inférieure est converti au type de données avec la priorité supérieure. Et pourtant, un autre point à considérer est si nous faisons des opérations arithmétiques sur des types décimaux que le type décimal résultant, c'est-à-dire la précision et l'échelle dépendent des opérandes et des opérations elles-mêmes. Ceci est décrit dans le document précision, échelle et longueur . P >

Ainsi, une partie de votre expression entre parenthèses p> xxx pré>

en utilisant des règles ci-dessus sur la précision et l'échelle des expressions décimales. En outre, l'arrondissement du banquier ou l'arrondi à même est utilisé. Il est important de noter que différents arrondis pour le type décimal et flotteur sont utilisés. Si nous continuons l'expression p> xxx pré>

de sorte que la partie de la divergence est due à une variation différente utilisée pour des types décimaux que pour le flotteur. P>

conformément à Les règles ci-dessus, il suffirait d'utiliser une seule montaise à l'intérieur de la parenthèse. Tous les autres littéraux seront promus pour flotter conformément aux règles de priorité de type de données. P>

1.0 / (1.0 / cast(60.0 as float))


0 commentaires

0
votes

Pour écrire une expression de flotteur constante, essayez d'utiliser la notation scientifique:

SELECT (1.0E0 / (1.0E0 / 60.0E0))

Le résultat est de 60.


0 commentaires