SQL Server'da garip bir işlem sorunu: -100 / -100 * 10 = 0


106
  • Eğer yürütürseniz SELECT -100/-100*10sonuç olur 0.
  • Eğer yürütürseniz SELECT (-100/-100)*10sonuç olur 10.
  • Eğer yürütürseniz SELECT -100/(-100*10)sonuç olur 0.
  • Eğer yürütürseniz SELECT 100/100*10sonuç olur 10.

BOL belirtir:

Bir ifadedeki iki operatör aynı operatör öncelik düzeyine sahip olduğunda, ifadedeki konumlarına göre soldan sağa değerlendirilirler.

Ve

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

BOL yanlış mı yoksa bir şey mi kaçırıyorum? Görünüşe göre -(beklenen) önceliği atıyor.


7
Sorunuz nedir?
Ilyes

14
Neden bitlerle ilgili olduğunu düşünüyorsun, tamsayılarla çalışıyorsun. Ve tamsayı / tamsayı = tamsayı. Yani -100 / -1000 eşittir 0
sepupic

5
Tamam, kabul ediyorum, bu -akışın "yanlış" gitmesine neden oluyor gibi görünüyor. Eğer denersen -100/(-100)*10sonucu alırsın 10. görülüyor ki /değerine karşı uygulandığı -denklemde ve daha sonra denklem 100*10belirlenmektedir. Bunun BOL ile ilgili bir hata olduğundan emin değilim, ancak daha çok SQL Server beklendiği gibi davranmıyor. Sql-docs hakkında bir konu gündeme getirmeye ve yanıtlarının orada ne olduğunu görmeye değer olabilir ; belki belgelere "özellik" hakkında bilgi veren bir not eklenebilir.
Larnu

3
SELECT -100/(-100)*10ayrıca 10 -değerini döndürür. Görünüşe göre , -yalnızca 100*10hesaplandıktan sonra uygulanması gereken operatör olarak kabul edilir
Panagiotis Kanavos

7
A / -B * Colduğunu A <div> <negate> B <multiply> C. Negate, dokümanlara göre çarpmadan daha düşük önceliğe sahiptir, dolayısıyla sonuç olur A / -(B * C). Kayan sabitleri kullanarak bunu daha açık bir şekilde görebilirsiniz: 12e / -13e * 14evs 12e / (-13e) * 14evs 12e / 13e * 14eBunun bizi atmasının nedeni, genellikle tekli eksi değerinin değişmezin bir parçası olmasını beklememiz veya en azından çok yüksek önceliğe sahip olmasıdır, ancak T-SQL böyle değildir İşler.
Jeroen Mostert

Yanıtlar:


96

Öncelik Tabloya göre bu olduğunu beklenen davranıştır. Daha yüksek önceliğe ( /ve *) sahip operatör, daha düşük önceliğe sahip (tekli -) operatörden önce değerlendirilir . Yani bu:

-100 / -100 * 10

şu şekilde değerlendirilir:

-(100 / -(100 * 10))

Bu davranışın, tekli olumsuzlamanın çarpma ve bölmeden daha yüksek önceliğe sahip olduğu çoğu programlama dilinden farklı olduğuna dikkat edin, örneğin VB , JavaScript .


38
Wow, T-SQL'deki bir başka değerli özellik :) Sanırım hataları aramak için tüm kodumu denetlemeliyim.
usr

14
oh adamım. Bu, çeşitli PHP üçlü operatör hatalarından bile daha kötüdür bugs.php.net/bug.php?id=61915 . Aklı başında insanlar, tekli operatörlerin ikili operatörlerden daha düşük önceliğe sahip olması gerektiğini düşünüyor?
phuclv

12
Gerçek fark, içinde -bir operatör olarak kabul edilip edilmeyeceği olabilir -100. Bazı dillerde, bir tamsayının sözdiziminin bir parçasıdır.
Barmar

7
Yani bu onların birliğinden önce gelen bir hatadır -.
Kevin

4
Ve karşı-sezgisel tasarımın galibi ...: Microsoft - bir kez daha
rexkogitans

34

BOL doğru. -göre daha düşük önceliğe sahiptir *, bu nedenle

-A * B

olarak ayrıştırılır

-(A * B)

Çarpma olduğu gibi, diğer iki ikili operatörü eşit önceliğe sahip /ve %(ve %bunun gibi bileşik ifadelerde nadiren kullanılır) karıştırmanın dışında, genellikle bunu fark etmezsiniz . Yani

C / -A * B

Olarak ayrıştırılır

C / -(A * B)

sonuçları açıklamak. Diğer birçok dilde, tekli eksi daha yüksek önceliğe sahiptir, çünkü bu karşı-sezgisel *ve /ancak T-SQL ve bu doğru belgelenmiştir.

Bunu göstermenin güzel (?) Bir yolu:

SELECT -1073741824 * 2

çünkü, bir aritmetik taşma üreten -(1073741824 * 2)üreten 2147483648bir in uymayan bir, bir ara ürün olarak INT, ancak

SELECT (-1073741824) * 2

beklenen sonucu üretir -2147483648, ki bu yapar.


"eksi" ikilidir. Tekli -"negatif" tir . "Eksi 10" demek istedikleri zaman "eksi 10" gibi şeyler söyleyenler kesin değil.
Birikim

11
@ Birikme: belirsizlik benim değil. -Tek işlenen uygulandığında operatörü, denir MINUSSQL sorgu planlarında. İkili karşılığı denir SUB. İsterseniz, "tekli eksi" kelimesini "eksi işaretiyle gösterilen tekli operatör" için bir kısaltma olarak yorumlayın - anlamsal bir atamadan ziyade sözdizimsel bir tanım.
Jeroen Mostert

3
"negatif 10" standart Amerikan kullanımıdır (inanıyorum), ancak Birleşik Krallık'ta standart değil.
Alchymist

12

Dokümantasyonda, öncelik sırasının (belki de sezginin tersine) - (Negative)üçüncü olduğuna dikkat edin .

Böylece etkili bir şekilde elde edersiniz:

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

Bunları değişkenlere yerleştirirseniz, çarpma işleminden sonra gerçekleşen tekli bir işlem olmadığı için bunun olduğunu görmezsiniz.

Yani burada A ve B aynıdır, oysa C, D, E gördüğünüz sonucu gösterir (E tam parantez içerdiğinde)

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.