2017-01-11 3 views
3

Ce problème m'a rendu fou. J'utilise Microsoft SQLExpress 2016 pour écrire une procédure stockée. Une des exigences est de faire des arrondis. Mais de temps en temps, l'arrondi est faux. J'ai découvert que l'arrondi T-SQL n'est pas exactement la même chose avec C#, mais pourquoi?TSQL Arrondi VS C# Arrondi

Comparer deux arrondi ci-dessous:

In T-SQL: ROUND(0.045, 2) --> this will produce 0.05 

In C#: Math.Round(0.045, 2) --> this will produce 0.04 

Pourquoi C# produit 0,04? Ne devrait-il pas être 0.05?

Que dois-je faire pour arrondir C# = arrondi T-SQL? Quelqu'un peut-il m'aider?

Merci, Sam


Sur curiousity, j'ai essayé cela en C#:

Math.Round(0.055, 2) 

Devinez, ce que C# arrondi à? Il arrondi à 0,06! Maintenant, je suis complètement confus!

Math.Round(0.045, 2) //this becomes 0.04 
Math.Round(0.055, 2) //this becomes 0.06 

Quelqu'un peut-il expliquer cela?

Merci

+3

double possible de [pourquoi-t-math-round2-5-retour 2 au lieu-de-3] (http://stackoverflow.com/questions/977796/why-dath-math-round2-5-return-2-instead-of-3). Réponse par Jon Skeet lui-même;) – J2D8T

+0

@ J2D8T pas vraiment un doublon, mais la ressource utile non-le-moins – HoneyBadger

Répondre

5

En effet, par défaut .NET à l'arrondissement 'Toeven', alors que SQL utilise 'AwayFromZero'. Voir This. Ce sont différentes méthodes d'arrondi, ils diffèrent dans la façon dont ils traitent 5. AwayFromZero l'arrondit au positif suivant ou au nombre négatif suivant. Donc, 0.5 devient 1, -0.5 devient -1. ToEven arrondit au nombre pair le plus proche. Donc 2.5 devient 2, 3.5 devient 4 (et de même pour les nombres négatifs). Les numéros autres que 5 sont traités de la même manière, ils sont arrondis au nombre le plus proche. Puisque 5 est équidistant de deux nombres, c'est un cas particulier, avec des stratégies différentes.

ToEven est également connu sous le nom de «règles bancaires», il est la valeur par défaut utilisée dans IEEE_754, qui est why c'est la valeur par défaut dans .NET. Inversement, AwayFromZero est également connu sous le nom de «Commercial Rounding». Je ne sais pas pourquoi c'est le serveur SQL par défaut, probablement parce que c'est la méthode la plus connue et la plus connue.

Bien sûr, vous pouvez toujours configurer ce que vous avez besoin:

En C# vous pouvez faire:

Math.Round(value, MidpointRounding.ToEven) 

ou

Math.Round(value, MidpointRounding.AwayFromZero) 

Dans SQL vous pouvez utiliser ROUND(), FLOOR() et/ou CEILING().

Laquelle des méthodes est la meilleure, dépend de ce que vous l'utilisez et de ce que vous voulez. Pour les collections/distributions raisonnables, la moyenne des valeurs arrondies à égales est la même que pour les valeurs d'origine. Ce n'est pas forcément le cas avec AwayFromZero. Si vous avez une collection contenant de nombreuses données .5, arrondir AwayFromZero traitera toutes ces valeurs de la même manière et introduira un biais. L'effet est que la moyenne des valeurs arrondies n'est pas la même que les valeurs d'origine. Le point d'arrondi est de rendre une valeur plus simple, alors qu'elle a le même sens.Ce n'est plus le cas si les moyennes ne correspondent pas; les valeurs arrondies ont une signification (légèrement?) différente des valeurs d'origine.

+2

J'écrivais la même réponse, avec un lien différent: https://msdn.microsoft.com/fr-fr/ library/system.midpointrounding (v = vs.110) .aspx # Anchor_3 donc +1 pour votre vitesse monsieur – SynerCoder

+0

@HoneyBadger vous êtes un sauveur de la vie! Merci mon pote! – Sam