Нуль без палочки

Ком­пью­те­ры не уме­ют вычи­тать чис­ла. Внут­ри про­цес­со­ра нет «вычи­та­то­ра», есть толь­ко сум­ма­тор (adder). Поэто­му когда надо посчи­тать, напри­мер, 3 — 2, ком­пью­тер внут­ри себя пере­пи­сы­ва­ет это выра­же­ние как 3 + (-2), то-есть, скла­ды­ва­ет трой­ку с минус двой­кой.

Чис­ла внут­ри ком­пью­те­ра, конеч­но же, дво­ич­ные. Самый зна­чи­мый бит в чис­ле — зна­ко­вый, если он 0, то чис­ло неот­ри­ца­тель­ное, а если 1 — то отри­ца­тель­ное. Если мы пишем сле­ва напра­во, так что самый зна­чи­мый бит — самый пер­вый сле­ва (к сло­ву, внут­ри себя ком­пью­те­ры же пишут по-еврей­ски, спра­ва нале­во (little endian)).

Так, зна­ко­вое целое чис­ло 3 запи­сы­ва­ет­ся как 0011 (пусть у меня будет четы­рёх­бит­ный про­цес­сор), а зна­ко­вое целое чис­ло ‑2 пишет­ся как 1110 (т.н. допол­ни­тель­ный код, two’s complement). Ну, и скла­ды­ва­ем эти чис­ла, поль­зу­ясь дво­ич­ной мате­ма­ти­кой, полу­ча­ем иско­мый 0001 (вер­нее, 10001, но про­цес­сор у нас четы­рёх­бит­ный, так что мни­мое пере­пол­не­ние идёт в игнор).

Все совре­мен­ные про­цес­со­ры (x86/AMD64, про­цес­со­ры ARM, и так далее) запи­сы­ва­ют отри­ца­тель­ные целые чис­ла, поль­зу­ясь допол­ни­тель­ным кодом. А вот на неко­то­рых более ран­них ком­пью­те­рах, типа PDP‑1 или совет­ской ЭВМ БЭСМ‑2, для запи­си таких чисел исполь­зо­вал­ся более про­стой обрат­ный код. Полу­чить обрат­ный код из дво­ич­но­го чис­ла про­ще — надо про­сто поме­нять еди­нич­ки на ноли­ки и наобо­рот. Так, что­бы запи­сать ‑2, берём +2 — это 0010, и меня­ем еди­нич­ки на ноли­ки, а ноли­ки на еди­нич­ки: 1101, вот вам и обрат­ный код.

И на этом месте появ­ля­ет­ся хох­ма!

Вот, напри­мер, обык­но­вен­ный нуль: 0000

Мож­но из него сде­лать отри­ца­тель­ный нуль: 1111

Таким обра­зом, у тебя в систе­ме есть два нуля — поло­жи­тель­ный и отри­ца­тель­ный, и запи­сы­ва­ют­ся они по-раз­но­му 🙂 И если ариф­ме­ти­че­ские дей­ствия с ними про­блем не вызы­ва­ют, так как на таких ком­пью­те­рах (-0 == +0) было TRUE, то с поби­то­вы­ми опе­ра­ци­я­ми, хеши­ро­ва­ни­ем, сор­ти­ров­кой уже воз­ни­ка­ют эффек­ты, и к кон­цу 1970х от про­сто­го обрат­но­го кода (one’s complement) для запи­си зна­ко­вых целых чисел отка­за­лись, перей­дя на запись допол­ни­тель­ным кодом (two’s complement), в кото­ром нуль как Аллах — один 🙂

Забав­но.

PS: А вооб­ще я стал­ки­вал­ся к неко­то­ры­ми зада­ча­ми, где мне бы при­го­ди­лось нали­чие двух нулей, отри­ца­тель­но­го и поло­жи­тель­но­го. А ещё было бы при­коль­но запи­сы­вать эти­ми раз­ны­ми нуля­ми резуль­та­ты вычис­ле­ния неко­то­рых пре­де­лов — было бы понят­нее, с какой сто­ро­ны пре­дел под­кра­ды­ва­ет­ся к нулю: lim (x → -∞) 1/x = ‑0 😉