JavaRush /Java блог /Random UA /Побітове заперечення чому так
Alex Bolgov
37 рівень
Ташкент

Побітове заперечення чому так

Стаття з групи Random UA
Привіт всім :) Під час прочитання статті Побітові операції у мене, як і в деяких, постало питання: а чому ж коли ми інвертуємо число 342, то отримуємо -343. Ось як це виглядає в статті: Побитове заперечення - чому так - 1У особливо допитливих (таких, як я) постало питання: "Гей, але ж 010101001 менше, ніж 101010110, логічно, що воно має бути менше 342 і позитивним". Вбиваючи в будь-якому онлайн-конвертері чисел або перевіряючи це за допомогою коду:
Integer a = Integer.valueOf("010101001", 2);
System.out.println(Integer.toString(a, 10));
несподівано отримуємо зовсім не -343...
169
Ех, як же добре, що колись давно на парах із програмування на C я якось миттю почув щось про знаковий розряд у цілих числах. Якийсь час погугливий, тепер я можу пояснити, що це за звір. Побітове заперечення - чому так - 2Насправді у статті є неточність, яка і ставить у глухий кут. Якщо ми перевіримо за допомогою коду, що дійсно є результатом інверсії числа 342:
int a = 342;
System.out.println(Integer.toBinaryString(~a));
то побачимо трохи інший результат
1111111111111111111111111010101001
Чому так? Вся справа в тому, що в змінній не може лежати просто 101010110, насправді воно зберігається як
00000000000000000000000101010110
Адже змінна типу int займає 4 байти, тобто. 32 біти - 32 осередки пам'яті. Після інверсії змінюються всі цифри, тобто. та "обрізані" на початку нулі. А тепер найцікавіше. Так як в бінарному поданні знак + або - перед числом зберегти не виходить, то існує одна хитрість: 1й біт насправді відповідає за знак і якраз є тим самим знаковим розрядом . А всі числа зберігаються за такою логікою: числа від 00...000 до 01...111 — позитивні, що починаються з 0 (тобто від 0 до 2147483647), а починаючи з 10...000 до 11... 111 - це негативні, починаючи з мінімального і закінчуючи -1 (тобто від -2147483648 до -1).
00000000000000000000000000000000 = 0
01111111111111111111111111111111 = 2147483647
10000000000000000000000000000000 = -2147483648
11111111111111111111111111111111 = -1
І далі ви запитаєте "Добре, Навальний, повіримо тобі, але чому ти вирішив, що це його палац" але як же при всьому цьому виходить -343? Все насправді просто. Ми можемо це просто порахувати вручну. Якщо ми від двійкової версії числа 342, що вийшла після інверсії ( 1111111111111111111111111010101001 ) "відріжемо" (або замінимо на 0) найперший біт і повернемо його назад в десяткову форму.
String s = "01111111111111111111111010101001";
System.out.println(s + " = " + Integer.toString(Integer.valueOf(s, 2), 10));
то отримаємо, що
011111111111111111111111010101001 = 2147483305
Насправді ж тут ми не просто "відрізали" 1 на початку, а відняли з цього числа 100000000000000000000000000000000. Тепер додамо його назад, але вже в десятковому вигляді. Що ми побачимо:
~342 =
11111111111111111111111010101001 =
//в двоичном виде//
01111111111111111111111010101001 +
10000000000000000000000000000000
=
//в десятичном виде//
-2147483648 + 2147483305 = -343
Ось і шукане число -343 :) Хлопці, це мій перший пост тут, поставте, будь ласка, йому лайк, якщо сподобалося і було пізнавально (дуже вже я хочу зібрати всі досягнення 😄) Докладніше на цю тему, можна почитати ось тут: Всім удачі і дякую за увагу)
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ