L'opération décimale de SQL Server n'est pas précise
Lorsque j'exécute cette opération simple sur le serveur SQL:
Select 800.0 /30.0
J'obtiens la valeur 26,666666, où même si elle arrondit à 6 chiffres, elle devrait être 26,666667. Comment puis-je obtenir un calcul précis? J'ai essayé de faire une recherche à ce sujet en ligne et j'ai trouvé une solution où j'ai converti chaque opérande en une décimale de haute précision avant l'opération, mais ce ne sera pas pratique pour moi car j'ai beaucoup de calculs longs et complexes. pense qu'il doit y avoir une meilleure solution.
Réponses
Lors d'une division utilisant, dans SQL Server, tous les chiffres après l'échelle résultante sont tronqués et non arrondis. Pour votre expression, vous avez un decimal(4,1)et un decimal(3,1), ce qui donne un decimal(10,6):
Precision = p1 - s1 + s2 + max(6, s1 + p2 + 1)
Scale = max(6, s1 + p2 + 1)
En conséquence, 26.66666666666666~est tronqué à 26.666666.
Vous pouvez contourner ce problème en augmentant la taille de la précision et de l'échelle, puis CONVERTrevenir à la précision et à l'échelle requises. Par exemple, augmentez la précision et l'échelle du decimal(3,1)vers decimal(5,2)et reconvertissez-le en decimal(10,6):
SELECT CONVERT(decimal(10,6),800.0 / CONVERT(decimal(5,3),30.0));
Cela revient 26.666667.
Cela peut être utile:
Utiliser ROUND (Transact-SQL)
SELECT ROUND(800.0 /30.0, 5) AS RoundValue;
Résultat:
RoundValue
26.666670
Je crois que c'est parce que SQL Server prend vos nombres comme des decimalvaleurs (qui sont exactes, par exemple, 6.6666 et 6.6667 signifient exactement ces valeurs, pas 6 et deux tiers) plutôt que des floatvaleurs (qui peuvent fonctionner avec des nombres approximatifs).
Si vous le lancez / le convertissez explicitement en un floatau début, vous devriez faire fonctionner vos calculs correctement.
Voici quelques exemples pour démontrer la différence entre int, decimalet floatcalculs
- Diviser 20 par 3
- Diviser 20 par 3, puis multiplier à nouveau par 3 (ce qui devrait être mathématiquement égal à 20).
SELECT (20/3) AS int_calc,
(20/3) * 3 AS int_calc_x3,
(CAST(20 AS decimal(10,3)) /3) AS dec_calc,
(CAST(20 AS decimal(10,3)) /3) * 3 AS dec_calc_x3,
(CAST(20 AS float) /3) AS float_calc,
(CAST(20 AS float) /3) * 3 AS float_calc_x3
avec les résultats suivants
int_calc int_calc_x3 dec_calc dec_calc_x3 float_calc float_calc_x3
6 18 6.666666 19.999998 6.66666666666667 20
Dans votre cas, vous pouvez utiliser
Select CAST(800.0 AS float) /30.0
ce qui donne 26,6666666666667
Notez que si vous multipliez ensuite par 30, le résultat est correct, par exemple,
Select (CAST(800.0 AS float) /30.0) * 30
donne 800. Les solutions traitant des nombres décimaux n'auront pas cela.
Notez également qu'une fois que vous l'avez en tant que flottant, il devrait rester un flottant jusqu'à ce qu'il soit reconverti en décimal ou en int d'une manière ou d'une autre (par exemple, enregistré dans une table en tant qu'int). Alors...
SELECT A.Num / 30
FROM (Select ((CAST(800.0 AS float) /30.0) * 30) AS Num) AS A
résultera toujours en 26,6666666666667
J'espère que cela vous aidera dans vos longs calculs complexes.