366

32-разрядные компьютеры могут хранить только целые числа со знаком до 2 31 - 1.
Вот почему у нас закончились адреса IPv4 и мы вступили в 64-битную эру.

Тем не менее, число 2 31 - 1 (2 147 483 647) не так велико, как число 1 триллион (1 000 000 000 000), которое, как мне кажется, я могу вывести на экран без поломки моей машины.

Может кто-нибудь объяснить, почему это так?

19 ответов19

785

Я отвечаю на ваш вопрос, задавая вам другой:

Как ты считаешь на пальцах до 6?

Вы, вероятно, рассчитываете до максимально возможного числа одной рукой, а затем переходите к второй руке, когда у вас кончатся пальцы. Компьютеры делают то же самое, если им нужно представить значение больше, чем может вместить один регистр, они будут использовать несколько 32-битных блоков для работы с данными.

398

Вы правы, что 32-разрядное целое число не может содержать значение больше 2 ^ 32-1. Однако значение этого 32-разрядного целого числа и то, как оно отображается на экране, - это две совершенно разные вещи. Напечатанная строка "1000000000000" не представлена 32-разрядным целым числом в памяти.

Для буквального отображения числа "1000000000000" требуется 13 байт памяти. Каждый отдельный байт может содержать значение до 255. Ни один из них не может содержать все числовое значение, но интерпретируется индивидуально как символы ASCII (например, символ « 0 » представлен десятичным значением 48, двоичное значение 00110000), их можно объединить в формат, который имеет смысл для ты, человек.


Связанное понятие в программировании - это приведение типов, то есть, как компьютер будет интерпретировать определенный поток 0 с и 1 с. Как и в приведенном выше примере, его можно интерпретировать как числовое значение, символ или даже что-то еще целиком. Хотя 32-разрядное целое число может не содержать значение 1000000000000, 32-разрядное число с плавающей запятой сможет это сделать, используя совершенно другую интерпретацию.

Что касается того, как компьютеры могут работать и обрабатывать большие числа внутри, существуют 64-разрядные целые числа (которые могут вмещать значения до 16 миллиардов миллиардов), значения с плавающей запятой, а также специализированные библиотеки, которые могут работать с произвольно большими номера.

190

Прежде всего, 32-разрядные компьютеры могут хранить числа до 2³²-1 в одном машинном слове. Машинное слово - это объем данных, которые ЦП может обработать естественным образом (т. Е. Операции с данными такого размера выполняются аппаратно и обычно выполняются быстрее всего). 32-битные процессоры используют слова, состоящие из 32 бит, поэтому они могут хранить числа от 0 до 2³²-1 в одном слове.

Во-вторых, 1 триллион и 1000000000000 - это две разные вещи.

  • 1 триллион - это абстрактное понятие числа
  • 1000000000000 это текст

Нажав 1 раз, а затем 0 12 раз, вы набираете текст. 1 входы 1 , 0 входов 0 . Увидеть? Вы печатаете символы. Символы не цифры. У пишущих машинок вообще не было процессора или памяти, и они справлялись с такими "цифрами" очень хорошо, потому что это просто текст.

Доказательство того, что 1000000000000 - это не число, а текст: оно может означать 1 триллион (в десятичном виде), 4096 (в двоичном виде) или 281474976710656 (в шестнадцатеричном). Он имеет еще больше значений в разных системах. Значение 1000000000000 - это число, и его сохранение - это отдельная история (мы вернемся к нему чуть позже).

Для хранения текста (в программировании это называется строка) 1000000000000 вам нужно 14 байтов (по одному на каждый символ плюс завершающий байт NULL, что в основном означает "строка заканчивается здесь"). Это 4 машинных слова. 3 с половиной было бы достаточно, но, как я уже сказал, операции над машинными словами выполняются быстрее всего. Давайте предположим, что ASCII используется для хранения текста, поэтому в памяти это будет выглядеть так: (преобразование кодов ASCII, соответствующих 0 и 1 в двоичный код, каждое слово в отдельной строке)

00110001 00110000 00110000 00110000
00110000 00110000 00110000 00110000
00110000 00110000 00110000 00110000
00110000 00000000 00000000 00000000

Четыре символа вписываются в одно слово, остальные перемещаются в следующее. Остальное перемещается к следующему слову, пока все (включая первый NULL-байт) не уместится.

Теперь вернемся к хранению номеров. Это работает так же, как с переполнением текста, но они располагаются справа налево. Это может показаться сложным, так что вот пример. Для простоты предположим, что:

  • наш воображаемый компьютер использует десятичный вместо двоичного
  • один байт может содержать числа 0..9
  • одно слово состоит из двух байтов

Вот пустая память из двух слов:

0 0
0 0

Давайте сохраним номер 4:

0 4
0 0

Теперь давайте добавим 9:

1 3
0 0

Обратите внимание, что оба операнда помещаются в один байт, но не результат. Но у нас есть еще один готовый к использованию. Теперь давайте сохраним 99:

9 9
0 0

Опять же, мы использовали второй байт для хранения числа. Давайте добавим 1:

0 0
0 0

Упс ... Это называется целочисленным переполнением и является причиной многих серьезных проблем, иногда очень дорогих.

Но если мы ожидаем, что переполнение произойдет, мы можем сделать это:

0 0
9 9

А теперь добавьте 1:

0 1
0 0

Это станет понятнее, если вы удалите разделенные байтами пробелы и символы новой строки:

0099    | +1
0100

Мы предсказали, что может произойти переполнение, и нам может понадобиться дополнительная память. Таким образом, обработка чисел происходит не так быстро, как с числами, которые помещаются в отдельные слова, и это должно быть реализовано в программном обеспечении. Добавление поддержки 32-разрядных чисел в 32-разрядном процессоре фактически делает его 64-разрядным процессором (теперь он может работать с 64-разрядными числами изначально, верно?).

Все, что я описал выше, относится и к двоичной памяти с 8-битными байтами и 4-байтовыми словами, это работает примерно так же:

00000000 00000000 00000000 00000000 11111111 11111111 11111111 11111111    | +1
00000000 00000000 00000000 00000001 00000000 00000000 00000000 00000000

Преобразование таких чисел в десятичную систему довольно сложно. (но это работает довольно хорошо с шестнадцатеричным)

40

Вы также можете написать "ЭТО ЗАЯВЛЕНИЕ ЛОЖНО" без сбоя вашего компьютера. это интерпретируется.

Edit: теперь меньше сарказма более полезной информации о различных способах число может быть сохранено в памяти. Я буду описывать их с более высокой абстракцией, то есть с точки зрения того, что современный программист может писать код, прежде чем он будет переведен в машинный код для выполнения.

Данные на компьютере должны быть ограничены определенным типом, и определение компьютера такого типа описывает, какие операции могут быть выполнены с этими данными и как (например, сравнивать числа, объединять текст или XOR - логическое значение). Вы не можете просто добавить текст к числу, так же как вы не можете умножить число на текст, поэтому некоторые из этих значений могут быть преобразованы между типами.

Давайте начнем с целых чисел без знака. В этих типах значений все биты используются для хранения информации о цифрах; Ваш пример 32-разрядного целого числа без знака, в котором может храниться любое значение от 0 до 2^32-1 . И да, в зависимости от языка или архитектуры используемой платформы у вас могут быть 16-разрядные или 256-разрядные целые числа.

Что делать, если вы хотите получить негатив? Интуитивно, целые числа со знаком - это название игры. Соглашение состоит в том, чтобы распределять все значения от -2^(n-1) до 2^(n-1)-1 - таким образом мы избегаем путаницы, когда приходится иметь дело с двумя способами записи +0 и -0 . Таким образом, 32-разрядное целое число со знаком будет содержать значение от -2147483648 до 2147483647 . Аккуратно, не правда ли?

Хорошо, мы рассмотрели целые числа, которые являются числами без десятичной составляющей. Выражать их сложнее: нецелая часть может быть разумно только где-то между 0 и 1 , поэтому каждый дополнительный бит, используемый для ее описания, будет увеличивать свою точность: 1/2, 1/4, 1/8 ... Проблема в том, что вы не можете точно выразить простой десятичный 0.1 как сумму дробей, у которых в знаменателе могут быть только степени двойки! Разве не было бы намного проще сохранить число как целое число, но согласились бы вместо этого поставить основную (десятичную) точку? Это называется числами с фиксированной запятой , где мы храним 1234100 но договорились о том, чтобы вместо этого читать его как 1234.100 .

Относительно более распространенным типом, используемым для вычислений, является число с floating point . То, как это работает, действительно опрятно, он использует один бит для хранения значения знака, а другой - для хранения показателя степени и значения. Существуют стандарты, определяющие такое распределение, но для 32-разрядного числа с плавающей запятой максимальное число, которое вы сможете сохранить, является подавляющим

(2 - 2^-23) * 2^(2^7 - 1) ≈ 3.4 * 10^38

Это, однако, происходит за счет точности. JavaScript, доступный в браузерах, использует 64-разрядные числа с плавающей запятой, и все еще не может понять все правильно. Просто скопируйте это в адресную строку и нажмите ввод. Оповещение о спойлере: результат не будет 0.3 .

javascript:alert(0.1+0.2);

Есть и другие альтернативные типы, такие как BigInteger Microsoft .NET 4.5, который теоретически не имеет верхних или нижних границ и должен рассчитываться в "пакетах"; но, возможно, более увлекательные технологии - это те, которые понимают математику, например, движок Wolfram Mathematica, который может точно работать с абстрактными значениями, такими как бесконечность.

31

Ключ к пониманию того, как компьютеры кодируют числа.

Правда, если компьютер настаивает на сохранении чисел с использованием простого двоичного представления числа с использованием одного слова (4 байта в 32-разрядной системе), то 32-разрядный компьютер может хранить только числа до 2 ^ 32. Но есть много других способов кодирования чисел в зависимости от того, чего вы хотите достичь с ними.

Одним из примеров является то, как компьютеры хранят числа с плавающей запятой. Компьютеры могут использовать целую кучу разных способов их кодирования. Стандарт IEEE 754 определяет правила для кодирования чисел больше 2 ^ 32. Грубо говоря, компьютеры могут реализовать это, разделив 32 бита на разные части, представляющие некоторые цифры числа, и другие биты, представляющие размер числа (т. Е. Показатель степени, 10 ^ x). Это позволяет гораздо больший диапазон чисел в терминах размера, но снижает точность (что хорошо для многих целей). Конечно, компьютер также может использовать более одного слова для этой кодировки, увеличивая точность величины доступных закодированных чисел. Простая десятичная 32-разрядная версия стандарта IEEE допускает числа с точностью примерно до 7 десятичных знаков и числа до 10 ^ 96 по величине.

Но есть много других вариантов, если вам нужна дополнительная точность. Очевидно, что вы можете использовать больше слов в своей кодировке без ограничений (хотя с потерей производительности для преобразования в и из кодированного формата). Если вы хотите исследовать один из способов, это можно сделать, есть отличная надстройка с открытым исходным кодом для Excel, которая использует схему кодирования, позволяющую вычислять сотни цифр точности. Надстройка называется Xnumbers и доступна здесь. Код написан на Visual Basic, который не является самым быстрым из возможных, но имеет то преимущество, что его легко понять и изменить. Это отличный способ узнать, как компьютеры выполняют кодирование более длинных чисел. И вы можете поиграть с результатами в Excel без необходимости установки каких-либо инструментов программирования.

24

Это все в твоем вопросе.

Вы можете написать любое число на бумаге. Попробуйте написать триллион точек на белом листе бумаги. Это медленно и неэффективно. Вот почему у нас есть десятизначная система для представления этих больших чисел. У нас даже есть имена для больших чисел, таких как "миллион", "триллион" и более, так что вы не говорите one one one one one one one one one one one... вслух.

32-разрядные процессоры предназначены для наиболее быстрой и эффективной работы с блоками памяти, длина которых составляет ровно 32 двоичных разряда. Но мы, люди, обычно используем 10-значную цифровую систему, а компьютеры, будучи электронными, используют 2-значную (двоичную) систему. Числа 32 и 64 просто имеют степень 2. Так же, как миллион и триллион - это силы 10. Нам легче работать с этими числами, чем, например, 65536.

Мы разбиваем большие числа на цифры, когда пишем их на бумаге. Компьютеры разбивают числа на большее количество цифр. Мы можем записать любое число, которое захотим, как и компьютеры, если мы их спроектируем.

15

32-битные и 64-битные относятся к адресам памяти. Память вашего компьютера похожа на почтовые ящики, каждый из которых имеет свой адрес. Центральный процессор (центральный процессор) использует эти адреса для адресации областей памяти в вашей оперативной памяти (оперативное запоминающее устройство). Когда процессор мог обрабатывать только 16-битные адреса, вы могли использовать только 32 МБ ОЗУ (что в то время казалось огромным). С 32-битным он пошел до 4+ ГБ (который казался огромным в то время). Теперь, когда у нас есть 64-битные адреса, оперативная память переходит в терабайты (что кажется огромным).
Однако программа может выделить несколько блоков памяти для таких вещей, как хранение чисел и текста, что зависит от программы и не связано с размером каждого адреса. Таким образом, программа может сообщить процессору, что я собираюсь использовать 10 адресных блоков памяти, а затем сохранить очень большое число, или 10-буквенную строку или что-то еще.
Примечание: адреса памяти указываются "указателями", поэтому 32- и 64-разрядные значения означают размер указателя, используемого для доступа к памяти.

13

Потому что отображение числа осуществляется с использованием отдельных символов, а не целых чисел. Каждая цифра в номере представлена отдельным символьным литералом, целочисленное значение которого определяется используемой кодировкой, например, 'a' представлено значением ascii 97 , а '1' - 49 . Проверьте таблицу ASCII здесь .
Для отображения «а» и «1» это то же самое. Это символьные литералы, а не целые числа. Каждый символьный литерал может иметь максимальное значение 255 на 32-битной платформе, сохраняя значение в 8-битном или 1-байтовом размере (это зависит от платформы, однако 8-битный является наиболее распространенным символьным размером), поэтому они могут быть сгруппированы вместе и могут быть отображается. Сколько отдельных символов они могут отображать, зависит от вашей оперативной памяти. Если у вас всего 1 байт ОЗУ, вы можете отобразить только один символ, если у вас 1 ГБ ОЗУ, вы можете хорошо отобразить 1024 * 1024 * 1024 символа (слишком лениво, чтобы делать математику).

Это ограничение, однако, относится к вычислениям, однако, думаю, вас интересует стандарт IPV4. Хотя это не совсем связано с bit-size , оно как-то повлияло на стандарты. При создании стандарта IPV4 они сохраняли значения ip в 32-разрядных целых числах. Теперь, когда вы дали размер, он стал стандартным. Все, что мы знаем об Интернете, зависело от этого, и затем у нас закончились IP-адреса для назначения. Поэтому, если стандарт IP был изменен на 64-разрядный, все просто перестанет работать, включая ваш маршрутизатор (я полагаю, это правильно) и другие сетевые устройства. Таким образом, должен быть создан новый стандарт, который просто поменял 32-битное целое на 128-битное. И скорректированы остальные стандартные. Производителю оборудования просто нужно заявить, что он поддерживает этот новый стандарт, и он станет вирусным. Хотя это не так просто, но я думаю, вы поняли это здесь.

Отказ от ответственности: большинство пунктов, упомянутых здесь, соответствуют моему предположению. Возможно, я упустил важные моменты, чтобы упростить его. Я не очень хорошо разбираюсь в числах, поэтому, должно быть, пропустил некоторые цифры, но я хочу ответить на вопрос ОП о том, почему он не сломает ПК.

12

В процессорах есть "слова". Есть разные слова. Когда люди говорят «32-битный процессор», они в основном имеют в виду "ширину шины памяти". Это слово состоит из различных "полей", которые относятся к подсистемам компьютера, соответствующим передаче (24 бита) и управлению (другие биты). Я могу ошибаться в точных цифрах, убедитесь в этом в руководствах.

Совершенно другой аспект - это вычисления. Наборы инструкций SSE и MMX могут хранить длинные целые числа. Максимальная длина без потери производительности зависит от текущей версии SSE, но она всегда кратна 64 битам.

Современные процессоры Opteron могут обрабатывать числа шириной 256 бит (я не уверен насчет целых чисел, но float точно).

Краткое описание: (1) ширина шины не связана напрямую с шириной вычисления, (2) даже разные слова (слово памяти, слово регистра, слово шины и т.д.) Не связаны друг с другом, в противном случае они имеют общий делитель около 8 или 16 или 24. Многие процессоры даже использовали 6-битное слово (но его история).

10

Разница заключается в том, как мы храним данные на компьютерах.

Вы правы, что для теоретической 8-битной машины мы можем хранить только 2 ^ 8 значений в одном регистре процессора или в памяти. (Пожалуйста, имейте в виду, что это зависит от "компьютера" до "компьютера" в зависимости от используемого процессора, архитектуры памяти и т.д. Но пока давайте придерживаться гипотетической "стереотипной" машины.)

Для теоретического 16-разрядного компьютера максимальное значение в регистре / ячейке памяти будет равно 2 ^ 16, для 32-разрядного компьютера - 2 ^ 32 и т.д.

На протяжении многих лет программисты изобрели все виды chicanery для хранения и обработки чисел больше, чем можно сохранить в одном регистре процессора или адрес памяти. Существует много методов, но все они включают использование более одного адреса регистра / памяти для хранения значений, превышающих ширину их "родного" регистра / области памяти.

Все эти методы полезны тем, что машина может хранить / обрабатывать значения, превышающие их исходную емкость. Недостатком является то, что почти все подходы требуют нескольких машинных инструкций / чтений / и т.д. обрабатывать эти цифры. Для случайного большого количества это не проблема. При работе с большим количеством больших чисел (в частности, с большими адресами памяти) накладные расходы замедляют работу.

Отсюда общее желание сделать регистры, ячейки памяти и аппаратные адреса памяти "шире" и шире, чтобы обрабатывать большие числа "изначально", чтобы такие числа можно было обрабатывать с минимальным количеством операций.

Поскольку размер числа бесконечен, регистр процессора / размер памяти / адресация всегда является балансом размера собственного числа и затрат, связанных с внедрением все большей и большей ширины.

10

Цель вычислительного устройства, как правило, состоит в том, чтобы принимать, обрабатывать, хранить и передавать данные. Базовое оборудование - это просто машина, которая помогает выполнять эти четыре функции. Это не может сделать ни один из тех без программного обеспечения.

Программное обеспечение - это код, который сообщает машине, как принимать данные, как их обрабатывать, как их хранить и как предоставлять их другим.

Базовое оборудование всегда будет иметь ограничения. В случае 32-битного компьютера большинство регистров, обрабатывающих данные, имеют ширину всего 32 бита. Это не означает, однако, что машина не может обрабатывать числа, превышающие 2 ^ 32, это означает, что если вы хотите работать с большими числами, машина может принять более одного цикла, чтобы принять его, обработать его, сохранить это или испустить это.

Программное обеспечение сообщает машине, как обрабатывать числа. Если программное обеспечение предназначено для обработки больших чисел, оно отправляет в ЦПУ серию инструкций, которые сообщают ему, как обрабатывать большие числа. Например, ваш номер может быть представлен двумя 32-битными регистрами. Если вы хотите добавить 1,234 к вашему номеру, программа скажет ЦПУ сначала добавить 1,234 к нижнему регистру, а затем проверить бит переполнения, чтобы увидеть, не привело ли это добавление к слишком большому числу для нижнего регистра. Если это так, то он добавляет 1 в верхний регистр.

Точно так же, как начальных школьников учат складывать с переносом, ЦПУ можно указывать обрабатывать числа больше, чем он может хранить в одном регистре. Это верно для большинства общих математических операций, для чисел любого практического размера.

8

32-битные компьютеры могут хранить числа до 2 ^ 32 в одном машинном слове, но это не значит, что они не могут обрабатывать большие объекты данных.

Смысл 32-битного компьютера, как правило, заключается в том, что шина данных и адресная шина имеют ширину 32 бита, что означает, что компьютер может одновременно обрабатывать 4 ГБ адресного пространства памяти и одновременно отправлять четыре байта данных по шине данных. ,

Это, однако, не ограничивает компьютер в обработке большего количества данных, ему просто нужно разделить данные на четыре байта, когда они отправляются по шине данных.

Обычный 32-разрядный процессор Intel может обрабатывать 128-разрядные числа внутри страны, что позволяет без проблем обрабатывать такие числа, как 100000000000000000000000000000000000000.

Вы можете обрабатывать гораздо большие числа, чем в компьютере, но тогда вычисления должны выполняться с помощью программного обеспечения, у ЦПУ нет инструкций для обработки чисел, превышающих 128 бит. (Он может обрабатывать гораздо большее число в форме чисел с плавающей запятой, но тогда у вас будет только 15 цифр точности.)

6

Просто добавив примечание ко многим другим ответам, потому что это довольно важный факт в этом вопросе, который был упущен.

"32 бита" относится к ширине адреса памяти. Это не имеет никакого отношения к размеру регистра. Многие 32-битные процессоры, вероятно, имеют 64 или даже 128-битные регистры. В частности, что касается линейки продуктов x86, последние потребительские ЦП, которые являются 64-битными, имеют до 256-битных регистров для специальных целей.

Эта разница между шириной регистра и шириной адреса существовала с древних времен, когда у нас было 4-битные регистры и 8-битные адреса, или наоборот.

Легко видеть, что сохранение большого числа не является проблемой независимо от размера регистра, как объяснено в других ответах.

Причина, по которой регистры, какого бы размера они ни были, могут также рассчитываться с большими числами, состоит в том, что слишком большие вычисления могут быть разбиты на несколько меньших, которые вписываются в регистры (это просто немного сложнее в действительности).

6

Ответы, которые уже даны, на самом деле довольно хороши, но они имеют тенденцию решать проблему с разных сторон и, таким образом, представляют неполную картину. Они также немного излишне технические, на мой взгляд.

Итак, просто чтобы прояснить то, на что намекают, но явно не выражены ни в одном из других ответов, и что, я думаю, является сутью вопроса:

Вы смешиваете несколько понятий в своем вопросе, и одно из них («32-битное») может фактически относиться к множеству разных вещей (и разные ответы предполагают разные интерпретации). Все эти концепции имеют какое-то отношение к числу битов (1 и 0), используемых (или доступных) в различных вычислительных контекстах (что я имею в виду под этим, я надеюсь, будет разъяснено в приведенных ниже примерах), но концепции в остальном не связаны.

Явное:

  • «IPv4/6» относится к интернет-протоколу, своду правил, определяющих, как информация должна быть упакована и интерпретирована в Интернете. Основное (или, по крайней мере, самое известное) различие между IPv4 и IPv6 заключается в том, что адресное пространство (т. Е. Набор адресов, которые можно использовать для различения разных мест в сети) больше в IPv6. Это связано с тем, сколько битов в каждом пакете данных, передаваемых по сети, выделено (т. Е. Отведено для цели) для идентификации отправителя пакета и предполагаемого получателя.
    • Не вычисляющая аналогия: каждый пакет похож на письмо, отправленное по обычной почте, а адресное пространство равно количеству символов, которое вам "разрешено" использовать при записи адреса и обратного адреса на конверте.
    • Я не вижу упоминания об этом ни в одном из других ответов.
  • "Слова" компьютерной памяти (32-разрядные и 64-разрядные) обычно можно рассматривать как наименьшую часть данных, которые компьютер использует или "мыслит". Эти биты данных собираются вместе, чтобы составить другие биты данных, такие как куски текста или большие целые числа.
  • 32-битные указатели могут быть или не быть словами, но они, тем не менее, рассматриваются атомарно (т.е. как отдельные единицы, которые не могут быть разбиты на более мелкие компоненты). Указатели - это самый низкоуровневый способ, с помощью которого компьютер может записать местоположение в памяти некоторого произвольного фрагмента данных. Обратите внимание, что размер указателя, используемый компьютером (или, собственно, операционной системой), ограничивает диапазон памяти, к которому может обращаться один указатель, поскольку существует только столько возможных областей памяти, на которые указатель может "указать" так как есть возможные значения для самого указателя. Это аналогично тому, как IPv4 ограничивает диапазон возможных интернет-адресов, но не ограничивает объем данных, которые могут присутствовать, например, на определенной веб-странице. Однако размер указателя не ограничивает размер самих данных, на которые может указывать указатель. (Для примера схемы, позволяющей размеру данных превышать диапазон указателей, посмотрите структуру указателей inode в Linux. Обратите внимание, что это использование слова "указатель" несколько отличается от обычного, поскольку указатель обычно относится к указателю на оперативную память, а не на место на жестком диске.)
    • Не вычислительная аналогия: хмммм ... это немного сложно. Возможно, десятичная система Дьюи для индексации библиотечных материалов немного похожа? Или любая система индексации, правда.
    • Смотрите ответ SiteNook.
    • Обратите внимание, что мое объяснение указателей выше элидирует некоторые тонкие детали и, возможно, не совсем верно. Однако в языках программирования, в которых программисты работают напрямую с указателями, нарисованный ментальный режим обычно достаточен для практических целей.
  • Цифры, которые компьютер "способен отображать" , не ограничиваются (для практических целей) аппаратным обеспечением или операционной системой компьютера; они рассматриваются как любой другой текст.

Обратите внимание, что это не является исчерпывающим списком толкований фразы «32 бита».

Дополнительный кредит: чтобы действительно увидеть философское различие между числами и примитивными кусками компьютерной памяти, прочитайте немного о машинах Тьюринга.

5

Если вам нужен практический пример того, как много программ в типичной системе Linux обрабатывают и выводят большое количество данных:

libgmp - Многофункциональная арифметическая библиотека GNU является наиболее широко используемой библиотекой для этой цели в системах Linux. Простой пример умножения 2 ^ 80 на 1000:

#include <gmp.h>

// Each large integer uses the mpz_t type provided by libgmp
mpz_t a_large_number;
mpz_t base;
mpz_t result;

// Initalize each variable
mpz_init(a_large_number);
mpz_init(base);
mpz_init(result);

// Assign the number 2 to the variable |base|
mpz_set_ui(base, 2);

// Raise base^80 (2^80), store the result in |a_large_number|
mpz_pow_ui(a_large_number, base, 80);

// Multiply |a_large_number| by 1000, store the result in |result|
mpz_mul_ui(result, a_large_number, 1000);

// Finally, output the result in decimal and hex notation
gmp_printf("decimal: %Zd, hex: %ZX\n", result, result);

Таким образом, в основном это то же самое, что и обычные операторы + - * /, просто с библиотекой для разбиения чисел и их внутреннего хранения в виде чисел с несколькими машинными словами (то есть 32-разрядных). Есть также функции типа scanf () для обработки преобразования текста в целочисленные типы.

Структура mpz_t точно такая же, как и у Скотта Чемберлена, который считает до 6 двумя руками. В основном это массив типов mp_limb_t размером с машинное слово, и когда число слишком велико, чтобы поместиться в машинное слово, GMP использует множественный mp_limb_t для хранения старших / младших частей числа.

5

Если вы напишите, например, 1000000000000 в калькуляторе, компьютер вычислит его как число действительного типа с десятичной точкой. Упомянутый вами предел для 32 бит касается больше всех чисел типа Integer без десятичной точки. Разные типы данных используют разные методы, как попасть в биты / байты.

Целочисленные номера типов: эта таблица может помочь вам понять суть (http://msdn.microsoft.com/en-us/library/296az74e.aspx). Это касается ограничений для C++. Например, номер типа Int64 имеет ограничения от -9223372036854775808 до 9223372036854775807.

Числа действительного типа: числа действительного типа содержат значение с плавающей запятой и показателем степени, и вы можете вводить намного большие числа, но с ограниченной точностью. (http://msdn.microsoft.com/en-us/library/6bs3y5ya.aspx) Например, LDBL (большой двойной) в C++ имеет максимальный показатель 308, так что, возможно, вы можете ввести или получить в результате число 9.999 x 10^308 означает, что теоретически у вас будет 308 (+1) цифр из 9 но для его представления будут использоваться только 15 самых важных цифр, остальные будут потеряны из-за ограниченной точности.

Кроме того, существуют разные языки программирования, и они могут иметь разные реализации ограничений по количеству. Таким образом, вы можете себе представить, что специализированные приложения могут обрабатывать гораздо большие (и / или более точные / точные) числа, чем C++.

5

В вашем уме вы знаете только 10 разных цифр. От 0 до 9 Внутренне в вашем мозгу это, конечно, закодировано иначе, чем в компьютере.

Компьютер использует биты для кодирования чисел, но это не важно. Именно так инженеры решили кодировать вещи, но вы должны это игнорировать. Вы можете представить себе, что 32-битный компьютер имеет уникальное представление более чем 4 миллиардов различных значений, в то время как мы, люди, имеем уникальное представление для 10 различных значений.

Всякий раз, когда мы должны постичь большее число, мы используем систему. Самый левый номер - самый важный. Это в 10 раз важнее следующего.

Компьютер, способный различать четыре миллиарда различных значений, также должен будет сделать крайнее левое значение в наборе значений в четыре миллиарда раз более важным, чем следующее значение в этом наборе. На самом деле компьютер не заботится вообще. Это не присваивает "важность" числам. Программисты должны сделать специальный код, чтобы позаботиться об этом.

Всякий раз, когда значение становится больше, чем количество уникальных символов, 9 в человеческом уме, вы добавляете один к числу слева.

3+3=6

В этом случае номер все еще вписывается в один "слот"

5+5=10. This situation is called an overflow.

Поэтому люди всегда сталкиваются с проблемой нехватки уникальных символов. Если компьютер не имеет системы, чтобы справиться с этим, он просто напишет 0, забыв, что было дополнительное число. К счастью, компьютеры имеют "флаг переполнения", который поднимается в этом случае.

987+321 is more difficult.

Возможно, вы изучили метод в школе. Алгоритм Алгоритм довольно прост. Начните с добавления двух крайних левых символов.

7+1=8, we now have ...8 as the result so far

Затем вы переходите к следующему слоту и выполняете такое же дополнение.

8+2=10, the overflow flag is raised. We now have ...08, plus overflow.

Поскольку у нас было переполнение, это означает, что мы должны добавить 1 к следующему числу.

9+3=12, and then we add one due to overflow. ...308, and we had another overflow.

Больше нет номеров, которые нужно добавить, поэтому мы просто создаем слот и вставляем 1, потому что флаг переполнения был поднят.

1308

Компьютер делает это точно так же, за исключением того, что он имеет 2 ^ 32 или даже лучше 2 ^ 64 различных символов, а не только 10, как люди.

На аппаратном уровне компьютер работает с одиночными битами, используя один и тот же метод. К счастью, это абстракция для программистов. Биты - только две цифры, потому что это легко представить в линии электропередачи. Либо свет включен, либо выключен.

Наконец, компьютер может отображать любое число в виде простой последовательности символов. Это то, что компьютеры лучше всего. Алгоритм преобразования между последовательностью символов и внутренним представлением довольно сложен.

3

Потому что вы отображаете не число (насколько это касается компьютера), а строку или последовательность цифр. Конечно, некоторые приложения (например, калькулятор, я полагаю), которые работают с числами, могут обрабатывать такое число, я думаю. Я не знаю, какие трюки они используют ... Я уверен, что некоторые другие, более сложные ответы охватывают это.

0

Большая часть содержания этого ответа изначально была получена из этого ответа (написанного до того, как другой вопрос был помечен как дубликат). Поэтому я обсуждаю использование 8-битных значений (хотя этот вопрос задавался о 32-битных значениях), но это нормально, потому что 8-битные значения проще для концептуального понимания, и те же понятия применимы к большим значениям, таким как 32-битная арифметика.

Когда вы добавляете два 8-битных числа, вы можете получить самое большое число (0xFF + 0xFF = 1FE). На самом деле, если вы умножите два 8-битных числа, самое большое число, которое вы можете получить (0xFF * 0xFF = 0xFE01), будет по-прежнему равным 16 битам, что в два раза больше 8 битов.

Теперь вы можете предполагать, что x-битный процессор может отслеживать только x-биты. (Например, 8-битный процессор может отслеживать только 8 бит.) Это не точно. 8-битный процессор получает данные в 8-битных порциях. (Эти "куски" обычно имеют формальный термин: "слово". На 8-битном процессоре используются 8-битные слова. На 64-битном процессоре можно использовать 64-битные слова.)

Итак, когда вы даете компьютеру 3 байта:
Байт № 1: инструкция MUL
Байт № 2: старшие байты (например, 0xA5)
Байт № 3: байты младшего разряда (например, 0xCB)
Компьютер может генерировать результат более 8 бит. Процессор может генерировать такие результаты:
0100 0000 0100 0010 хххх хххх хххх хххх 1101 0111
иначе:
0x4082xxxxD7
Теперь позвольте мне истолковать это для вас:
0x означает, что следующие цифры шестнадцатеричные.
Я кратко расскажу о "40".
82 является частью регистра "А", который представляет собой последовательность из 8 битов.
xx и xx являются частью двух других регистров, называемых регистром "B" и регистром "C". Причина, по которой я не заполнил эти биты нулями или единицами, состоит в том, что инструкция "ДОБАВИТЬ" (отправляемая в ЦП) может привести к тому, что эти биты не будут изменены инструкцией (тогда как большинство других битов, которые я использую в этом примере, может изменить, за исключением некоторых битов флага).
D7 поместится в большем количестве битов, называемых регистром "D".
Регистр это просто кусок памяти. Регистры встроены в ЦП, поэтому ЦП может получать доступ к регистрам без необходимости взаимодействия с памятью на карте памяти.

Таким образом, математический результат 0xA5 умножить на 0xCB равен 0x82D7.

Теперь, почему биты были разделены на регистры A и D вместо регистров A и B или регистров C и D? Ну, еще раз, это пример сценария, который я использую, и должен был быть похож на концепцию реального языка ассемблера (Intel x86 16-битный, используемый Intel 8080 и 8088 и многими новыми процессорами). Могут существовать некоторые общие правила, такие как регистр "C", обычно используемый в качестве индекса для операций подсчета (типичный для циклов), и регистр "B", используемый для отслеживания смещений, которые помогают указывать области памяти. Таким образом, "А" и "D" могут быть более распространенными для некоторых общих арифметических функций.

Каждая инструкция CPU должна иметь некоторую документацию, используемую людьми, которые программируют на ассемблере. В этой документации должно быть указано, какие регистры используются каждой инструкцией. (Таким образом, выбор используемых регистров часто определяют разработчики ЦП, а не программисты на языке ассемблера. Хотя, может быть некоторая гибкость.)

Теперь вернемся к "40" в приведенном выше примере: это серия битов, часто называемая "регистром флагов". Каждый бит в регистре флагов имеет имя. Например, есть бит "переполнения", который ЦП может установить, если результат будет больше, чем пространство, в котором может храниться один байт результатов. (Бит "переполнения" часто может называться сокращенным названием "OF"). Это заглавная буква, а не ноль.) Программное обеспечение может проверить значение этого флага и заметить "проблему". Работа с этим битом часто незаметно обрабатывается языками более высокого уровня, поэтому начинающие программисты часто не учатся взаимодействовать с флагами процессора. Однако программисты на ассемблере могут обычно обращаться к некоторым из этих флагов способом, очень похожим на другие переменные.

Например, у вас может быть несколько инструкций ADD. Одна инструкция ADD может хранить 16 бит результатов в регистре A и регистре D, тогда как другая инструкция может просто хранить 8 младших битов в регистре A, игнорировать регистр D и указывать бит переполнения. Затем, позже (после сохранения результатов регистра A в основное ОЗУ), вы можете использовать другую инструкцию ADD, которая хранит только 8 старших бит в регистре (возможно, регистр A.) Нужно ли вам использовать флаг переполнения, может зависеть только от того, какую инструкцию умножения вы используете.

(Существует также обычно флаг "недостаточного количества", если вы вычитаете слишком много, чтобы соответствовать желаемому результату.)

Просто чтобы показать вам, как сложные вещи получили:
Intel 4004 был 4-битным процессором
Intel 8008 был 8-битным процессором. Он имел 8-битные регистры с именами A, B, C и D.
Intel 8086 был 16-разрядным процессором. Он имел 16-битные регистры с именами AX, BX, CX и DX.
Intel 80386 был 32-разрядным процессором. Он имел 32-битные регистры с именами EAX, EBX, ECX и EDX.
Процессоры Intel x64 имеют 64-разрядные регистры с именами RAX, RBX, RCX и RDX. Чипы x64 могут выполнять 16-битный код (в некоторых режимах работы) и могут интерпретировать 16-битные инструкции. При этом биты, которые составляют регистр AX, составляют половину битов, которые составляют регистр EAX, которые являются половиной битов, которые составляют регистр RAX. Поэтому, когда вы меняете значение AX, вы также меняете EAX и RAX, потому что те биты, которые используются в AX, являются частью битов, используемых RAX. (Если вы измените EAX на значение, кратное 65 536, младшие 16 бит не изменятся, поэтому AX не изменится. Если вы измените EAX на значение, не кратное 65 536, то это также повлияет на AX.)

Есть больше флагов и регистров, чем я упомянул. Я просто выбрал несколько часто используемых, чтобы привести простой концептуальный пример.

Теперь, если вы используете 8-битный процессор, при записи в память вы можете столкнуться с некоторыми ограничениями в отношении возможности ссылаться на адрес 8 бит, а не на адрес 4 или 16 бит. Детали будут различаться в зависимости от процессора, но если у вас есть такие ограничения, то процессор может иметь дело с 8-битными словами, поэтому ЦП чаще всего называют «8-битным процессором».

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .