web-dev-qa-db-fra.com

Un problème de fonctionnement étrange dans SQL Server: -100 / -100 * 10 = 0

  • Si vous exécutez SELECT -100/-100*10 Le résultat est 0.
  • Si vous exécutez SELECT (-100/-100)*10 le résultat est 10.
  • Si vous exécutez SELECT -100/(-100*10) le résultat est 0.
  • Si vous exécutez SELECT 100/100*10 Le résultat est 10.

BOL indique:

Lorsque deux opérateurs dans une expression ont le même niveau de priorité d'opérateur, ils sont évalués de gauche à droite en fonction de leur position dans l'expression.

Et

Level   Operators
  1     ~ (Bitwise NOT)
  2     * (Multiplication), / (Division), % (Modulus)
  3     + (Positive), - (Negative), + (Addition), + (Concatenation), - (Subtraction), & (Bitwise AND), ^ (Bitwise Exclusive OR), | (Bitwise OR)

Est-ce que BOL est mauvais, ou est-ce que je manque quelque chose? Il semble que - Annule la priorité (attendue).

106
cuizizhe

Selon le tableau de priorité, ceci est le comportement attendu. L'opérateur de priorité supérieure (/ et *) est évalué avant l'opérateur avec une priorité inférieure (unaire -). Donc ça:

-100 / -100 * 10

est évalué comme:

-(100 / -(100 * 10))

Notez que ce comportement est différent de la plupart des langages de programmation où la négation unaire a une priorité plus élevée que la multiplication et la division, par ex. VB , JavaScript .

94
Salman A

BOL est correct. - A une priorité inférieure à *, Donc

-A * B

est analysé comme

-(A * B)

La multiplication étant ce qu'elle est, vous ne le remarquez généralement pas, sauf lorsque vous mélangez les deux autres opérateurs binaires avec la même priorité: / Et % (Et % Est rarement utilisé dans des expressions composées comme celle-ci). Alors

C / -A * B

Est analysé comme

C / -(A * B)

expliquer les résultats. Ceci est contre-intuitif car dans la plupart des autres langues, le signe moins unaire a une priorité plus élevée que * Et /, Mais pas en T-SQL, et cela est correctement documenté.

Une belle (?) Façon de l'illustrer:

SELECT -1073741824 * 2

produit un débordement arithmétique, car -(1073741824 * 2) produit 2147483648 comme intermédiaire, qui ne rentre pas dans un INT, mais

SELECT (-1073741824) * 2

produit le résultat attendu -2147483648, ce qui fait.

34
Jeroen Mostert

Notez dans la documentation que (peut-être contre-intuitivement) l'ordre de priorité de - (Negative) est troisième.

Vous obtenez donc efficacement:

-(100/-(100*10)) = 0

Si vous les placez dans des variables, vous ne verrez pas cela se produire, car aucune opération unaire ne se produit après la multiplication.

Donc, ici A et B sont les mêmes, alors que C, D, E montrent le résultat que vous voyez (avec E ayant le crochet complet)

DECLARE @i1 int, @i2 int, @i3 int;

SELECT @i1 = -100,
       @i2 = -100,
       @i3 = 10;

SELECT @i1/@i2*@i3      [A],
       -100/(-100)*10   [B],
       -100/-100*10     [C],
       -100/-(100*10)   [D],
       -(100/-(100*10)) [E];

A - 10
B - 10
C - 0
D - 0
E - 0
11
Jamie Pollard