Если 32-разрядные машины могут обрабатывать только числа до 2 ^ 32, почему я могу записать 1000000000000 (триллион) без сбоя моей машины?


369

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

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

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


35
Вопрос некорректен. 32-битные машины могут обрабатывать числа, намного превышающие 2 ^ 32. Они делают это постоянно, с «длинным» и так далее. Они могут хранить только 2 ^ 32 в одном регистре, но программное обеспечение написано, чтобы обойти эту проблему. Некоторые современные языки даже не имеют проблемы с длиной данного числа.
JFA

23
Пожалуйста, оставляйте комментарии по теме, вежливо и актуально для технических аспектов вопроса. Почти 50 комментариев в шутку уже пришлось удалить, и мы хотели бы избежать блокировки поста. Спасибо.
nhinkle

6
Этот вопрос был написан немного небрежно. Что вы подразумеваете под «написать» и «отобразить» число 1000000000000? Когда вы написали вопрос, вы написали число 1000000000000, и ваш веб-браузер отображает его просто отлично, я полагаю, но это не должно быть ничего странного для любого, кто когда-либо использовал компьютер раньше. Вопрос требует свободной интерпретации.
Здравствуйте, до свидания

7
Предполагается, что человеческое сознание содержит около 50 бит (я где-то читал). Таким образом, вопрос не в том, «Как я могу написать 10^9без сбоя моего ПК?» а скорее "Как я могу писать 10^(18)без разрушения моего мозга?"
Хаген фон Айцен

1
32-разрядные компьютеры могут хранить только целые числа без знака до 2 ^ 32 - 1. 2 ^ 32 - 1 даже не равно 2 147 483 647 ... 300 повышенных голосов, и никто не понял этого?
Корай Тугай

Ответы:


784

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

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

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


16
Забавно, @ кодовое имя. Как тогда вы рассчитываете на свои пальцы до 32 или более (то есть, когда 2 ^ 5 исчерпан)? ;) Хорошая аналогия перехода на другую руку ... даже если двоичный код задерживает необходимость перехода на другую руку. То, что я хотел бы видеть, это подсчитывать до 1024 или более с ловкостью педали, чтобы перейти к пальцам ног для дальнейшего счета в двоичном - до 1 048 575! :) Это потенциально 20-битная мощность дочерней платы. : P
J0e3gan

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

@ кодовое имя - просто, вы назначаете один палец в качестве указателя стека. Как только у вас кончатся пальцы, вы добавляете сумму в стек и возобновляете подсчет.
Мач

Где ты это узнал, @codename? Я впервые услышал это от Фредерика Поля, см., Например, здесь hjkeen.net/halqn/f_pohl3.htm
Зейн

2
Я думаю, что это не ответ на соответствующий вопрос. Ответ @ Bigbio2002 является правильным. Здесь «1000000000000» - это не число, а текст, как «adsfjhekgnoregrebgoregnkevnregj». То, что вы говорите, правда, но я твердо чувствую, что это не правильный ответ. И чтобы увидеть так много голосов ...
Главный начальник

398

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

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


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

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


22
На самом деле это в основном правильно, но не совсем. 32-значное число с плавающей запятой вряд ли сможет точно представить 1000000000000. Оно будет представлять число, очень очень близкое к желаемому числу, но не совсем так.
Тим Б

6
@TimB: Вы слышали о десятичном формате? Это часть стандарта IEEE 754-2008. Этот формат способен корректно представлять это число :)
VX

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

2
@TimB действительно. Самое близкое число к тому, которое может быть представлено как float32: 999999995904
greggo

4
@TimB: Но 64-битное число с плавающей запятой может легко представлять 1000000000000точно. Сейчас 10 ^ 12 или 2 ^ 12 * 5 ^ 12; 5 ^ 12 требует 28 бит мантиссы.
Кит Томпсон

191

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

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

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

Нажав 1один раз, а затем 012 раз, вы печатаете текст. 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

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


21
Ваш ответ звучит довольно снисходительно. ОП четко говорит о количестве, а не о тексте large as the number 1 trillion (1000000000000). Кроме того, вы почти говорите об арифметике с произвольной точностью , но вы никогда не упоминаете ни одного из терминов того, что вы говорите ...
MirroredFate

12
«1 триллион» - это тоже строка
Эльзо Валуги

3
@ ElzoValugi Это так. Мне нужно было найти способ представить концепцию абстрактного числа, а не строку, представляющую число. Я считаю, что «1 триллион» - лучший и менее двусмысленный способ сделать это (см. Доказательство в ответе).
Гроностай

25
@MirroredFate Я не согласен с «ясно говорит о количестве». OP говорит : «отображается нормально», в котором четко будет говорить о тексте «1000000000000» ко мне ...
Джо

4
@yannbane 'A' - это символ, а не число. '?' это символ, а не число. «1» - это символ, а не число. Персонажи - это просто символы. Они могут представлять цифры или цифры, но определенно они не являются числами. «1» может обозначать одну, десять, сто, тысячу и т. Д., Это просто символ, который обозначает цифру, которая может быть числом или его частью. «10» (строка символов) может означать два, восемь, десять или шестнадцать и т. Д., Но когда вы говорите, что у вас десять яблок, вы используете число десять, и все знают, что вы имеете в виду. Существует огромная разница между персонажами и числами.
Гроностай

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);

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


8
Вы можете сделать это в этой реальности. Попробуйте сделать это во вселенной Star Trek. Просто отойди назад, из-за всех искр и дыма.
Майкл Петротта

Это не совсем то, как работает фиксированная точка. На самом деле это система, в которой числа масштабируются и смещаются для получения десятичной точки. В вашем примере масштаб составляет 1/1000, но есть также числа с фиксированной запятой (особенно в компьютерной графике), такие как: 0 = 0,0, 255 = 1,0 - масштаб 1/255.
Андон М. Коулман

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 МБ ОЗУ (что в то время казалось огромным). С 32bit он пошел до 4 + ГБ (который казался огромным в то время). Теперь, когда у нас есть 64-битные адреса, оперативная память переходит в терабайты (что кажется огромным).
Однако программа может выделять несколько блоков памяти для таких вещей, как хранение чисел и текста, что зависит от программы и не связано с размером каждого адреса. Таким образом, программа может сообщить процессору, что я собираюсь использовать 10 адресных блоков памяти, а затем хранить очень большое число, или 10-буквенную строку или что-то еще.
Примечание: адреса памяти указываются «указателями», поэтому 32- и 64-разрядные значения означают размер указателя, используемого для доступа к памяти.


2
Хороший ответ, за исключением деталей - 16 бит адресного пространства дали вам 64 КБ, а не 32 МБ, а машины, подобные 286, имели 24-разрядные адреса (для 16 МБ). Кроме того, с 64-разрядными адресами вы выходите далеко за пределы терабайтов - больше похоже на 16 экзабайт - терабайты находятся в пределах ограничений, накладываемых материнскими платами / процессорами нынешнего поколения, а не размера адресов.
Фил

4
32-разрядный относится к размеру машинного слова, а не к адресам памяти. Как упоминал Фил, 286 был 16-битным процессором, но использовал 24 бита для адресации посредством сегментации памяти. Процессоры x86 32-битные, но используют 36-битную адресацию. Смотрите PAE .
Гроностай

@gronostaj хорошо x86 имеет 32-битную адресацию от 386 до Pentium.
Руслан

Upvote, потому что это единственный ПРАВИЛЬНЫЙ ответ здесь - 32-битный относится к 32-битной адресации памяти, а не 32-битной арифметике.
user1207217

@ user1207217: ?? Так, по вашему мнению, например, Z80 или 8080 являются 16-битными процессорами (из-за 16-битной адресации памяти и шины памяти)?
Пабук

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-битное. И скорректированы остальные стандартные. Производителю оборудования просто нужно заявить, что он поддерживает этот новый стандарт, и он станет вирусным. Хотя это не так просто, но я думаю, вы поняли это здесь.

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


2
Я не отрицал, но есть ряд проблем с вашим ответом. 10x31 в ASCII, а не 0x1. 1 ГБ = 1024 ^ 3 B. IPv4 был изобретен до того, как были введены 32-разрядные ЦП, поэтому утверждение о том, что адреса хранятся в 32-разрядных целых числах, противоречит вопросу OP. И наконец, IPv6 использует 128-битные адреса, а не 64-битные.
Гроностай

13

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

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

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

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


Неверно, оригинальный процессор Pentium имел 64-битную шину данных для высокой пропускной способности памяти, хотя это был 32-битный процессор. 8088 был 16-битным процессором с 8-битной шиной данных.
doug65536

10

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

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

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

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

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


10

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

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

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

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

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

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

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


8

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

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

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

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

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


6

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

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

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

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

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


Это не совсем правда; то, что относится к 64-битному, противоречиво, но системы с шириной регистра 64 бит часто называют 64-битными. Википедия говорит, что «64-битная компьютерная архитектура обычно имеет целочисленные и адресные регистры шириной 64 бита». Да, современная линейка продуктов x86 (или AMD-64) имеет огромные регистры специального назначения, но они имеют 64-битные основные регистры и могут получать доступ к 48-52 битам памяти; старые системы x86 имеют 32-битные основные регистры и имеют доступ к 24-36 битам памяти, а 8086 назывался 16-битным чипом, имел 16-битные регистры ширины и обращался к 20 битам памяти.
Просфилаес

@prosfilaes Это много ценной информации, я имел в виду ее (я не запомнил детали так же хорошо, как ты). Не стесняйтесь редактировать это в ответ.
Мафу

6

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

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

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

Явное:

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

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

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


Я думаю, что ссылка на IPv4 заключалась в том, чтобы указать, что количество адресов IPv4 фактически ограничено длиной 32-разрядного целого числа со знаком, тогда как IPv6 использует 128 битов и, следовательно, может иметь на много порядков больше адресов.
Clonkex

@ Clonkex Возможно, хотя это определенно не вопрос сформулирован.
Кайл Стрэнд,

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 ++.


Этот «ответ» неверен: калькуляторы используют представление чисел BCD, чтобы избежать ошибок усечения. IE 0.1 десятичное не может быть точно представлено как двоичное число конечной длины.
опилки

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

В вашем уме вы знаете только 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, как люди.

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

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


По- моему, я знаю 36, но обычно использую только 16 из них.
Кайл Стрэнд,

«Компьютер использует биты для кодирования чисел, но это не важно». В контексте того, что пользователь спрашивает о 32-битных словах и о том, как они используются для хранения чисел больше 2 ^ 32-1, очень важно.
HörmannHH

Не важно, как вы кодируете числа в памяти вашего мозга. У вас есть конечное число представлений; большинство выучили 10 разных символов. Внутри вашего мозга это, вероятно, представлено в виде тысяч нейронов и синапсов. В компьютере он представлен в виде электричества или без электричества на линии электропередачи. С точки зрения программирования - или при изучении математики, это совсем не важно, за исключением редкого случая, когда вы программируете непосредственно для определенного набора процессоров. Он спрашивает о 32-битных и 64-битных, а не отдельных битах.
frodeborli

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 xxxx xxxx xxxx xxxx 1101 0111
aka:
0x4082xxxxD7
Теперь позвольте мне интерпретировать это для вас:
0x означает, что следующие цифры являются шестнадцатеричными.
Я буду обсуждать "40" более подробно в ближайшее время.
82 является частью регистра «A», который представляет собой последовательность из 8 битов.
xx и xx являются частью двух других регистров, называемых регистром «B» и регистром «C». Причина, по которой я не заполнил эти биты нулями или единицами, состоит в том, что инструкция «ДОБАВИТЬ» (отправленная в ЦП) может привести к тому, что эти биты не изменятся инструкцией (тогда как большинство других битов, которые я использую в этом примере, может изменить, за исключением некоторых битов флага).
D7 поместится в большем количестве битов, называемых регистром «D».
Регистр это просто кусок памяти. Регистры встроены в ЦП, поэтому ЦП может обращаться к регистрам без необходимости взаимодействия с памятью на карте памяти.

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

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

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

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

Например, у вас может быть несколько инструкций 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-битным процессором».


Я чувствую, что части моего ответа повторяют некоторые другие ответы на этот вопрос. Однако, это не было замечено, когда я впервые написал содержание, так как я написал это для другого вопроса. Также, хотя я ценю ответ Animism, включая некоторый код на языке C, я чувствовал, что мой контент предоставил некоторые подробности о том, как работает Assembly, что ближе к фактическим действиям / дизайну ЦП. Таким образом, мой ответ не пытается быть превосходящим ответом, который «лучше чем» всех других, но только дополнительный; добавив еще одну перспективу с некоторой дополнительной проницательностью
TOOGAM
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.