2017-10-14 2 views
2

La représentation binaire du nombre entier 170 est 1 0 1 0 1 0 1 0 Inverser les bits donne 0 1 0 1 0 1 0 1 qui a converti en décimal est entier 85.TSQL Négation binaire

Pourquoi SELECT ~170 retour -171? J'ai du mal à comprendre ce qui me manque ici.

+0

Essayez 'SELECT ~ CAST (170 AS tinyint);' pour éviter de fonctionner sur un entier de 32 bits. –

+0

Merci, cela donne la réponse que je m'attendais, à savoir, 85. – AAsk

Répondre

3

Ce n'est pas un octet (8 bits), c'est probablement un nombre de 32 bits.

Quelle que soit la longueur (16, 32 ou 64), il aura 0 s. En 16 bits, cela ressemble à:

0000 0000 1010 1010 devient 1111 1111 0101 0101 qui est -171.

Vous pouvez le faire vous-même avec la calculatrice Windows avec le mode programmeur, décimal, et tout autre chose que l'octet sélectionné. Entrez 170 et appuyez sur NOT et vous obtiendrez -171, et il vous montrera les représentations de bits de chacun.

Une autre chose à noter serait que 1010 1010 n'est pas réellement 170, s'il s'agit d'un octet signé. Comme un octet signé ce serait -86. L'inverser en mode octet donne 85, comme prévu.

Notez également la différence entre les modèles binaires signés et non signés. La longueur de bit est importante, car pour les entiers signés, un nombre qui commence par 1 est négatif, et vous obtenez la valeur absolue de ce nombre négatif en inversant les bits et en en ajoutant un. (Voir: Two's Complement)

C'est pourquoi 1010 1010 (comme un octet) donne un nombre positif si vous inversez, et pourquoi 0000 0000 1010 1010 donne un nombre négatif si vous l'inverser.

Pour référence, les types intégrés dans le serveur SQL sont:

  • tinyint: octet (1 octet) (8 bits) (non signés)
  • smallint: mot (2 octets) (16 bits), (signé)
  • int: dword (4 octets) (32 bits), (signé)
  • bigint: QWORD (8 octets) (64 bits) (signé)

Notez que bien que j'ai décrit les octets signés, il semble que SQL Server n'a pas d'octets signés du tout, et n'a pas du tout de type entier non signé plus grand. Donc, si vous utilisez tinyint, il sera toujours non signé, et si vous utilisez quelque chose de plus grand, il sera toujours signé.

+0

S'il utilise 15 bits, vous obtiendrez 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 comme vous le suggérez. Inverser les bits donne 1 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 qui converti en décimal est 65365 et non -171. – AAsk

+1

@AAsk '1111 1111 0101 0101' sous la forme d'un entier signé de 16 bits est -171. Comme un * entier non signé * de 16 bits, c'est 65365, oui. –

+0

Merci; Cela me permet de mieux comprendre ce qui se passe.Cependant, je trouve cela un peu étrange car TSL (pour autant que je sache) n'a pas la fonctionnalité pour spécifier INT comme signé ou non signé. – AAsk