383

32-bit computers can only store signed integers up to 231 - 1.
This is why we have run out of IPv4 addresses and have entered the 64-bit era.

However, the number 231 - 1 (2,147,483,647) is not as large as the number 1 trillion (1,000,000,000,000) which I seem to be able to display fine without my machine crashing.

Can someone explain why this is?

9
  • 38
    The question is flawed. 32-bit machines can handle numbers much larger than 2^32. They do it all the time, with 'long' and so on. They can only store up to 2^32 in one register, but the software is written to bypass this problem. Some modern languages don't even have a problem with the length of a given number.
    – jfa
    Jan 11, 2014 at 17:46
  • 25
    Please keep comments on-topic, polite, and relevant to the technical aspects of the question. Nearly 50 joke comments already had to be removed, and we'd like to avoid having to lock the post. Thank you.
    – nhinkle
    Jan 11, 2014 at 22:05
  • 6
    This question has been written in a way that is a bit sloppy. What do you mean by "write" and "display" the number 1000000000000? When you wrote the question you wrote the number 1000000000000, and your web browser displays it just fine, I assume, but this should be nothing strange to anyone that has ever used a computer before. The question asks for free interpretation. Jan 12, 2014 at 1:39
  • 10
    The human consciousness is estimated to hold about 50 bits (I read somewhere). So the question is not "How can I write 10^9 without my PC crashing?" but rather "How can I write 10^(18) without my brain crashing?" Jan 18, 2014 at 9:38
  • 1
    32 bit computers can only store UNSIGNED integers up to 2^32 - 1. 2^32 - 1 is not even equal to 2,147,483,647... 300 up-votes and nobody realised this? Mar 4, 2015 at 18:21

19 Answers 19

795

I answer your question by asking you a different one:

How do you count on your fingers to 6?

You likely count up to the largest possible number with one hand, and then you move on to your second hand when you run out of fingers. Computers do the same thing, if they need to represent a value larger than a single register can hold they will use multiple 32bit blocks to work with the data.

7
  • 16
    Funny, @codename. How then do you count on your fingers to 32 or more (i.e. once 2^5 is exhausted)? ;) The analogy of moving to one's other hand is good...even if binary delays the need to move to one's other hand. What I would like to see is counting to 1,024 or more with the pedial dexterity to move to one's toes for further counting in binary - up to 1,048,575! :) That's potentially 20-bits of daughterboard power. :P
    – J0e3gan
    Jan 10, 2014 at 16:17
  • 14
    Please keep comments on-topic and relevant to discussing the technical aspects of this answer. Over 60 joke comments have already been deleted from this answer, and we'd like to avoid having to lock the post.
    – nhinkle
    Jan 11, 2014 at 22:03
  • @codename- easy, you assign one finger as a stack pointer. Once you run out of fingers you add the amount to the stack and restart counting.
    – Makach
    Jan 16, 2014 at 10:37
  • Where did you learn that, @codename? I heard this first from Frederik Pohl, see e.g. here hjkeen.net/halqn/f_pohl3.htm
    – Zane
    Jan 17, 2014 at 15:15
  • 2
    I think this is not the answer to the relevant question. Answer by @Bigbio2002 is the correct one. Here "1000000000000" is not a number but a text, just like "adsfjhekgnoregrebgoregnkevnregj". What you are saying is true, but I strongly feel this is not the correct answer. And to see so many upvotes... Jan 18, 2014 at 4:40
397

You are correct that a 32-bit integer cannot hold a value greater than 2^32-1. However, the value of this 32-bit integer and how it appears on your screen are two completely different things. The printed string "1000000000000" is not represented by a 32-bit integer in memory.

To literally display the number "1000000000000" requires 13 bytes of memory. Each individual byte can hold a value of up to 255. None of them can hold the entire, numerical value, but interpreted individually as ASCII characters (for example, the character '0' is represented by decimal value 48, binary value 00110000), they can be strung together into a format that makes sense for you, a human.


A related concept in programming is typecasting, which is how a computer will interpret a particular stream of 0s and 1s. As in the above example, it can be interpreted as a numerical value, a character, or even something else entirely. While a 32-bit integer may not be able to hold a value of 1000000000000, a 32-bit floating-point number will be able to, using an entirely different interpretation.

As for how computers can work with and process large numbers internally, there exist 64-bit integers (which can accommodate values of up to 16-billion-billion), floating-point values, as well as specialized libraries that can work with arbitrarily large numbers.

9
  • 22
    Actually that is mostly correct but not quite. A 32 point floating point number is unlikely to be able to accurately represent 1000000000000. It will represent a number very very close to the desired number but not exactly it.
    – Tim B
    Jan 9, 2014 at 10:54
  • 7
    @TimB: Have you heard about decimal32 format? It's part of IEEE 754-2008 standard. This format is capable of correct representation of this number:)
    – V-X
    Jan 9, 2014 at 12:54
  • 16
    True, that can. However that is not the format people mean when they say "float", which usually refers to a 32bit floating point number as stored and used by standard floating point processors in current computers.
    – Tim B
    Jan 9, 2014 at 13:06
  • 2
    @TimB indeed. The closest number to that which can be represented as a float32 is 999999995904
    – greggo
    Jan 9, 2014 at 18:03
  • 4
    @TimB: But a 64-bit floating-point number can easily represent 1000000000000 exactly. It's 10^12, or 2^12 * 5^12; 5^12 requires 28 bits of mantissa. Jan 11, 2014 at 19:54
190

First and foremost, 32-bit computers can store numbers up to 232-1 in a single machine word. Machine word is the amount of data the CPU can process in a natural way (ie. operations on data of that size are implemented in hardware and are generally fastest to perform). 32-bit CPUs use words consisting of 32 bits, thus they can store numbers from 0 to 232-1 in one word.

Second, 1 trillion and 1000000000000 are two different things.

  • 1 trillion is an abstract concept of a number
  • 1000000000000 is text

By pressing 1 once and then 0 12 times you're typing text. 1 inputs 1, 0 inputs 0. See? You're typing characters. Characters aren't numbers. Typewriters had no CPU or memory at all and they were handling such "numbers" pretty well, because it's just text.

Proof that 1000000000000 isn't a number, but text: it can mean 1 trillion (in decimal), 4096 (in binary) or 281474976710656 (in hexadecimal). It has even more meanings in different systems. Meaning of 1000000000000 is a number and storing that number is a different story (we'll get back to it in a moment).

To store the text (in programming it's called a string) 1000000000000 you need 14 bytes (one for each character plus a terminating NULL byte that basically means "the string ends here"). That's 4 machine words. 3 and a half would be enough, but as I said, operations on machine words are the fastest. Let's assume ASCII is used for text encoding, so in memory it will look like this: (converting ASCII codes corresponding to 0 and 1 to binary, each word in a separate line)

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

Four characters fit in one word, the rest is moved to the next one. The rest is moved to next word until everything (including first NULL byte) fits.

Now, back to storing numbers. It works just like with overflowing text, but they are fitted from right to left. It may sound complicated, so here's an example. For the sake of simplicity let's assume that:

  • our imaginary computer uses decimal instead of binary
  • one byte can hold numbers 0..9
  • one word consists of two bytes

Here's an empty 2-word memory:

0 0
0 0

Let's store the number 4:

0 4
0 0

Now let's add 9:

1 3
0 0

Notice that both operands would fit in one byte, but not the result. But we have another one ready to use. Now let's store 99:

9 9
0 0

Again, we have used second byte to store the number. Let's add 1:

0 0
0 0

Whoops... That's called integer overflow and is a cause of many serious problems, sometimes very expensive ones.

But if we expect that overflow will happen, we can do this:

0 0
9 9

And now add 1:

0 1
0 0

It becomes clearer if you remove byte-separating spaces and newlines:

0099    | +1
0100

We have predicted that overflow may happen and we may need additional memory. Handling numbers this way isn't as fast as with numbers that fit in single words and it has to be implemented in software. Adding support for two-32-bit-word-numbers to a 32-bit CPU effectively makes it a 64-bit CPU (now it can operate on 64-bit numbers natively, right?).

Everything I have described above applies to binary memory with 8-bit bytes and 4-byte words too, it works pretty much the same way:

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

Converting such numbers to decimal system is tricky, though. (but it works pretty well with hexadecimal)

10
  • 21
    Your answer reads rather condescendingly. OP is clearly talking about the number, not the text: large as the number 1 trillion (1000000000000). Also, you are almost talking about Arbitrary-precision arithmetic, but you never really mention any of the terms for what you are saying.... Jan 8, 2014 at 1:22
  • 13
    "1 trillion" is also a string Jan 8, 2014 at 9:46
  • 3
    @ElzoValugi It is. I had to find some way to present the concept of abstract number, as opposed to string representing a number. I believe "1 trillion" is a better and less ambiguous way to do it (see the proof in answer).
    – gronostaj
    Jan 8, 2014 at 11:09
  • 26
    @MirroredFate I disagree with 'is clearly talking about the number'. OP says 'displayed fine', which clearly is talking about the text '1000000000000' to me...
    – Joe
    Jan 8, 2014 at 20:49
  • 4
    @yannbane 'A' is a character and not a number. '?' is a character and not a number. '1' is a character and not a number too. Characters are just symbols. They can represent digits or numbers, but definitely they aren't numbers. '1' can stand for one, ten, hundred, thousand and so on, it's just a symbol that stands for a digit that can be a number or its part. '10' (string of characters) can mean two or eight or ten or sixteen etc. but when you say you have ten apples, you're using a number ten and everybody knows what you mean. There's a huge difference between characters and numbers.
    – gronostaj
    Jan 9, 2014 at 15:52
40

You are also able to write "THIS STATEMENT IS FALSE" without your computer crashing :) @Scott's answer is spot-on for certain calculation frameworks, but your question of "writing" a large number implies that it's just plain text, at least until it's interpreted.

Edit: now with less sarcasm more useful information on different ways a number can be stored in memory. I'll be describing these with higher abstraction i.e. in terms that a modern programmer may be writing code in before it's translated to machine code for execution.

Data on a computer has to be restricted to a certain type, and a computer definition of such type describes what operations can be performed on this data and how (i.e. compare numbers, concatenate text or XOR a boolean). You can't simply add text to a number, just like you can't multiply a number by text so some of these values can be converted between types.

Let's start with unsigned integers. In these value types, all bits are used to store information about digits; yours is an example of a 32-bit unsigned integer where any value from 0 to 2^32-1 can be stored. And yes, depending on the language or architecture of the platform used you could have 16-bit integers or 256-bit integers.

What if you want to get negative? Intuitively, signed integers is the name of the game. Convention is to allocate all values from -2^(n-1) to 2^(n-1)-1 - this way we avoid the confusion of having to deal with two ways to write +0 and -0. So a 32-bit signed integer would hold a value from -2147483648 to 2147483647. Neat, isn't it?

Ok, we've covered integers which are numbers without a decimal component. Expressing these is trickier: the non-integer part can sensibly only be somewhere between 0 and 1, so every extra bit used to describe it would increase its precision: 1/2, 1/4, 1/8... The problem is, you can't precisely express a simple decimal 0.1 as a sum of fractions that can only have powers of two in their denominator! Wouldn't it be much easier to store the number as an integer, but agree to put the radix (decimal) point instead? This is called fixed point numbers, where we store 1234100 but agree on a convention to read it as 1234.100 instead.

A relatively more common type used for calculations is floating point. The way it works is really neat, it uses one bit to store the sign value, then some to store exponent and significand. There are standards that define such allocations, but for a 32-bit float the maximum number you would be able to store is an overwhelming

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

This however comes at the cost of precision. JavaScript available in browsers uses 64-bit floats, and it still can't get things right. Just copy this into the address bar and press enter. Spoiler alert: the result is not going to be 0.3.

javascript:alert(0.1+0.2);

There are more alternative types like Microsoft .NET 4.5's BigInteger, which theoretically has no upper or lower bounds and has to be calculated in "batches"; but perhaps the more fascinating technologies are those that understand math, like Wolfram Mathematica engine, which can precisely work with abstract values like infinity.

2
  • 9
    You can do that in this reality. Try doing that in the Star Trek universe. Just stand back before, because of all the sparks and smoke. Jan 8, 2014 at 1:17
  • That is not exactly how fixed-point works. It is actually a system where numbers are scaled and biased to produce the decimal point. In your example the scale is 1/1000, but there are also fixed-point numbers (especially in computer graphics) like this: 0 = 0.0, 255 = 1.0 - the scale is 1/255. Jan 10, 2014 at 19:26
31

The key is understanding how computers encode numbers.

True, if a computer insists on storing numbers using a simple binary representation of the number using a single word (4 bytes on a 32 bit system), then a 32 bit computer can only store numbers up to 2^32. But there are plenty of other ways to encode numbers depending on what it is you want to achieve with them.

One example is how computers store floating point numbers. Computers can use a whole bunch of different ways to encode them. The standard IEEE 754 defines rules for encoding numbers larger than 2^32. Crudely, computers can implement this by dividing the 32 bits into different parts representing some digits of the number and other bits representing the size of the number (i.e. the exponent, 10^x). This allows a much larger range of numbers in size terms, but compromises the precision (which is OK for many purposes). Of course the computer can also use more than one word for this encoding increasing the precision of the magnitude of the available encoded numbers. The simple decimal 32 version of the IEEE standard allows numbers with about 7 decimal digits of precision and numbers of up to about 10^96 in magnitude.

But there are many other options if you need the extra precision. Obviously you can use more words in your encoding without limit (though with a performance penalty to convert into and out of the encoded format). If you want to explore one way this can be done there is a great open-source add-in for Excel that uses an encoding scheme allowing hundreds of digits of precision in calculation. The add-in is called Xnumbers and is available here. The code is in Visual Basic which isn't the fastest possible but has the advantage that it is easy to understand and modify. It is a great way to learn how computers achieve encoding of longer numbers. And you can play around with the results within Excel without having to install any programming tools.

0
24

It's all in your question.

You can write any number you like on paper. Try writing a trillion dots on a white sheet of paper. It's slow and ineffective. That's why we have a 10-digit system to represent those big numbers. We even have names for big numbers like "million", "trillion" and more, so you don't say one one one one one one one one one one one... out loud.

32-bit processors are designed to work most quick and efficiently with blocks of memory that are exactly 32 binary digits long. But we, people, commonly use 10-digit numeric system, and computers, being electronic, use 2-digit system (binary). Numbers 32 and 64 just happen to be powers of 2. So are a million and a trillion are powers of 10. It's easier for us to operate with these numbers than multitudes of 65536, for example.

We break big numbers into digits when we write them on paper. Computers break down numbers into a greater number of digits. We can write down any number we like, and so may the computers if we design them so.

0
15

32bit and 64bit refer to memory addresses. Your computer memory is like post office boxes, each one has a different address. The CPU (Central Processing Unit) uses those addresses to address memory locations on your RAM (Random Access Memory). When the CPU could only handle 16bit addresses, you could only use 32mb of RAM (which seemed huge at the time). With 32bit it went to 4+gb (which seemed huge at the time). Now that we have 64bit addresses the RAM goes into terabytes (which seems huge).
However the program is able to allocate multiple blocks of memory for things like storing numbers and text, that is up to the program and not related to the size of each address. So a program can tell the CPU, I'm going to use 10 address blocks of storage and then store a very large number, or a 10 letter string or whatever.
Side note: Memory addresses are pointed to by "pointers", so the 32- and 64-bit value means the size of the pointer used to access the memory.

8
  • 2
    Good answer except for the details - 16bits of address space gave you 64kb, not 32mb, and machines like the 286 had 24-bit addresses (for 16mb). Also, with 64-bit addresses, you go well beyond terabytes - more like 16 exabytes - terabytes is around the kind of limits motherboards/CPUs of the present generation are imposing - not the size of the addresses.
    – Phil
    Jan 8, 2014 at 7:58
  • 4
    32-bit refers to machine word size, not memory addresses. As Phil mentioned, 286 was 16-bit CPU but used 24 bits for addressing through memory segmentation. x86 CPUs are 32-bit, but use 36-bit addressing. See PAE.
    – gronostaj
    Jan 8, 2014 at 8:30
  • @gronostaj well x86 are have 32-bit addressing from 386 to Pentium.
    – Ruslan
    Jan 8, 2014 at 9:17
  • Upvote because this is the only CORRECT answer here - 32bit refers to 32bit memory addressing, not 32bit arithmetic. Jan 8, 2014 at 15:42
  • @user1207217: ?? So according to your reasoning for example Z80 or 8080 are 16-bit processors (because of 16-bit memory addressing and memory bus)? Jan 8, 2014 at 22:21
13

Because displaying the number is done using individual characters, not integers. Each digit in the number is represented with a separate character literal, whose integer value is defined by the encoding being used, for example 'a' is represented with ascii value 97, while '1' is represented with 49. Check the ascii table here.
For displaying both 'a' and '1' is same. They are character literals, not integers. Each character literal is allowed to have max value of 255 in 32-bit platform storing the value in 8 bit or 1 byte size(That's platform dependent, however 8 bit is most common character size), thus they can be grouped together and can be displayed. How much separate characters they can display depends upon the RAM you have. If you have just 1 byte of RAM then you can display just one character, if you have 1GB of RAM, you can display well 1024*1024*1024 characters(Too lazy to do the math).

This limitation however applies to the calculations, however I guess you're interested about the IPV4 standard. Although it's not entirely related to computers's bit-size, it's somehow affected the standards. When IPV4 standard created, they stored the ip values in 32-bit integers. Now once you gave the size, and it became standard. Everything we know about internet was dependent on that, and then we ran out of IP addresses to assign. So if the IP standard was revised to have 64 bit, everything will just stopped working, including your router(I assume this to be correct) and other networking devices. So a new standard has to be created, which just swapped the 32 bit integer with 128 bit one. And adjusted rest of the standard. Hardware manufacturer just need to declare that they support this new standard and it'll get viral. Although it's not that simple, but I guess you got the point here.

Disclaimer: Most of the points mentioned here are true to my assumption. I may have missed important points here to make it simpler. I am not good with numbers, so must have missed some digits, but my point here is to reply the OP's answer about why it won't crash the PC.

1
  • 2
    I haven't downvoted, but there's a number of problems with your answer. 1 is 0x31 in ASCII, not 0x1. 1 GB = 1024^3 B. IPv4 wad invented before 32-bit CPUs were introduced, so saying that addresses were stored in 32-bit integers is in conflict with OP's question. And finally IPv6 is using 128-bit addresses, not 64-bit.
    – gronostaj
    Jan 8, 2014 at 7:37
13

In processors, there is "words". There is different words. When people say "32 bit processor", they mean mostly "memory bus width". This word consists of different "fields", which refer to subsystems of computer corresponding to transmitting (24 bits) and control (other bits). I can be wrong about exact numbers, make yourself sure about it through manuals.

Completely different aspect is computation. SSE and MMX instruction sets can store long integers. Maximal lenght without loss of productivity depends on current SSE version but its always about multiple of 64bits.

Current Opteron processors can handle 256 bit wide numbers (I'm not sure about integer, but float is for sure).

Summary: (1) bus width is not connected to computation width directly, (2) even different words (memory word, register word, bus word etc) do not connected to each other, other then they have common divisor about 8 or 16 or 24. Many processors even used 6 bit word (but its history).

1
  • Not true, the original Pentium processor had a 64-bit data bus for high memory bandwidth, even though it was a 32-bit processor. The 8088 was a 16-bit processor with an 8-bit data bus.
    – doug65536
    Jan 11, 2014 at 23:21
11

The difference lies in how we store data in computers.

You are correct that for a theoretical 8-bit machine, we are only able to store 2^8 values in a single processor register or memory address. (Please keep in mind this varies from "machine" to "machine" based on processor used, memory architecture, etc. But for now, let's stick with a hypothetical 'stereotype' machine.)

For a theoretical 16-bit machine, the max value in a register/memory location would be 2^16, for a 32-bit machine, 2^32, etc.

Over the years, programmers have devised all sorts of chicanery to store and handle numbers greater than can be stored in a single processor register or memory address. Many methods exist, but they all involve using more than one register/memory address to store values larger than their "native" register/memory location width.

All of these methods are beneficial in that the machine can store/process values larger than their native capacity. The downside is almost all approaches require multiple machine instructions/reads/etc. to handle these numbers. For the occasional large number, this isn't a problem. When dealing with lots of large numbers (large memory addresses in particular) the overhead involved slows things down.

Hence the general desire to make registers, memory locations and memory address hardware "wider" and wider in order to handle large numbers "natively" so such numbers can be handled with the minimum number of operations.

Since number size is infinite, processor register/memory size/addressing is always a balance of native number size and the costs involved in implementing larger and larger widths.

10

The purpose of a computing device, generally, is to accept, process, store, and emit data. The underlying hardware is merely a machine that helps perform those four functions. It can do none of those without software.

Software is the code that tells the machine how to accept data, how to process it, how to store it, and how to provide it to others.

The underlying hardware will always have limitations. In the case of a 32 bit machine, most of the registers that process data are only 32 bits wide. This doesn't mean, though, that the machine can't handle numbers beyond 2^32, it means that if you want to deal with larger numbers, it may take the machine more than one cycle to accept it, process it, store it, or emit it.

The software tells the machine how to handle numbers. If the software is designed to handle large numbers, it sends a series of instructions to the CPU that tell it how to handle the larger numbers. For instance, your number can be represented by two 32 bit registers. If you wanted to add 1,234 to your number, the software would tell the CPU to first add 1,234 to the lower register, then check the overflow bit to see if that addition resulted in a number too big for the lower register. If it did, then it adds 1 to the upper register.

In the same way elementary schoolchildren are taught to add with carry, the CPU can be told to handle numbers larger than it can hold in a single register. This is true for most generic math operations, for numbers of any practical size.

8

32 bit computers can only store numbers up to 2^32 in a single machine word, but that doesn't mean that they can't handle larger entities of data.

The meaning of a 32 bit computer is generally that the data bus and address bus is 32 bits wide, which means that the computer can handle 4 GB of memory address space at once, and send four bytes of data at a time over the data bus.

That however doesn't limit the computer from handling more data, it just have to divide the data into four byte chunks when it's send over the data bus.

The regular Intel 32-bit processor can handle 128-bit numbers internally, which would let you handle numbers like 100000000000000000000000000000000000000 without any problem.

You can handle much bigger numbers than that in a computer, but then the calculations have to be done by software, the CPU doesn't have instructions for handling numbers larger than 128 bits. (It can handle much larger number in the form of floating point numbers, but then you only have 15 digits of precision.)

6

Just adding a note to the many other answers, because this is a pretty important fact in this question that has been missed.

"32 bit" refers to the memory address width. It has nothing to do with the register size. Many 32 bit CPUs likely have 64 or even 128 bit registers. In particular referring to the x86 product line, the recent consumer CPUs, which are all 64bit, posses up to 256 bit registers for special purposes.

This difference between the register width and the address width has existed since ancient times, when we had 4 bit registers and 8 bit addresses, or vice versa.

It is simple to see that storing a large number is no problem regardless of the register size, as explained in other answers.

The reason why the registers, of whatever size they may happen to be, can additionally also calculate with larger numbers, is that too large calculations can be broken down into several smaller ones that do fit into the registers (it's just a tiny bit more complicated in reality).

2
  • That's not really true; what 64 bit refers to is inconsistent, but systems with register widths of 64 bit are frequently called 64 bit. Wikipedia says "a 64-bit computer architecture generally has integer and addressing registers that are 64 bits wide". Yes, the modern x86 (or AMD-64) product line has huge special purpose registers, but they have 64 bit main registers and can access 48-52 bits of memory; the older x86 systems have 32 bit main registers and access 24-36 bits of memory, and the 8086 was called a 16-bit chip, had 16-bit wide registers and accessed 20 bits of memory.
    – prosfilaes
    Jan 18, 2014 at 12:40
  • @prosfilaes That's a lot of valuable information, I was referring to those (I failed to remember the details as well as you did tho). Feel free to edit this into the answer.
    – mafu
    Jan 19, 2014 at 20:41
6

The answers already given are actually pretty good, but they tend to address the issue from different sides and thus present an incomplete picture. They're also a bit overly technical, in my opinion.

So, just to clarify something that's hinted at but not explicitly expressed in any of the other answers, and which I think is the crux of the matter:

You're mixing up several concepts in your question, and one of them ("32 bit") can actually refer to a variety of different things (and different answers have assumed different interpretations). These concepts all have something to do with the number of bits (1's and 0's) used (or available) in various computing contexts (what I mean by this will hopefully be clarified by the examples below), but the concepts are otherwise unrelated.

Explicitly:

  • "IPv4/6" refers to internet protocol, a set of rules defining how information is to be packaged and interpreted on the internet. The primary (or at least the most well-known) distinction between IPv4 and IPv6 is that the address space (i.e. the set of addresses that can be used to distinguish between different locations on the network) is larger in IPv6. This has to do with how many bits in each packet of data sent across the network are allocated for (i.e. set aside for the purpose of) identifying the packet's sender and intended recipient.
    • Non-computing analogy: Each packet is like a letter sent via snail-mail, and the address space is like the amount of characters you're "allowed" to use when writing the address and return-address on the envelope.
    • I don't see this mentioned in any of the other answers so far.
  • Computer-memory "words" (32-bit and 64-bit) can generally be thought of as the smallest piece of data that a computer uses, or "thinks" in. These bits of data come together to make up other bits of data, such as chunks of text or larger integers.
  • 32-bit pointers may or may not be words, but they are nevertheless treated atomically (i.e. as individual units that can't be broken down into smaller components). Pointers are the lowest-level way in which a computer can record the location in memory of some arbitrary chunk of data. Note that the pointer size used by the computer (or, really, by the operating system) limits the range of memory that can be accessed by a single pointer, since there are only as many possible memory locations that a pointer can "point" to as there are possible values for the pointer itself. This is analogous to the way in which IPv4 limits the range of possible internet addresses, but does not limit the amount of data that can be present in, for instance, a particular web page. However, pointer size does not limit the size of the data itself to which the pointer can point. (For an example of a scheme for allowing data size to exceed pointer range, check out Linux's inode pointer structure. Note that this is a slightly different use of the word "pointer" than is typical, since pointer usually refers to a pointer in to random access memory, not hard drive space.)
    • Non-computing analogy: hmmmm....this one's a bit tricky. Perhaps the Dewey decimal system for indexing library materials is a bit similar? Or any indexing system, really.
    • See SiteNook's answer.
    • Please note that my explanation of pointers above elides some subtle details and is arguably not entirely correct. However, in programming languages in which programmers work directly with pointers, the mental mode I've drawn is usually sufficient for practical purposes.
  • The numbers that a computer is "able to display" are not (for practical purposes) limited by the computer's hardware or operating system; they are treated like any other text.

Note that this is not intended to be a comprehensive list of interpretations for the phrase "32 bit."

Extra credit: to really see the bare-bones philosophical distinction between numbers and primitive chunks of computer memory, read a bit about Turing machines.

2
  • I think the reference to IPv4 was to point out that the number of IPv4 addresses is effectively limited to the length of a signed 32-bit integer, whereas IPv6 uses 128 bits and can therefore have many orders of magnitude more addresses.
    – Clonkex
    Jul 21, 2017 at 6:26
  • @Clonkex Possibly, although that's definitely not the question is phrased. Jul 21, 2017 at 14:00
5

If you write 1000000000000 for example in calculator, computer will calculate it as a Real type number with decimal point. Limit for 32 bits you mentioned touches more all the Integer type numbers without decimal point. Different data types use different methods how to get into bits/bytes.

Integer type numbers: This table could help you catch the point (http://msdn.microsoft.com/en-us/library/296az74e.aspx). This touches limits for C++. For example Int64 type number has limits from -9223372036854775808 to 9223372036854775807.

Real type numbers: Real type numbers contain value with floating point and exponent and you can enter much larger numbers, but with limited accuracy/precision. (http://msdn.microsoft.com/en-us/library/6bs3y5ya.aspx) For example LDBL (large double) in C++ has maximum exponent 308, so possibly you can enter or have as a result number 9.999 x 10^308, means you will have theoretically 308(+1) digits of 9 but only 15 most important digits will be used to represent it, rest will be lost, cause of limited precision.

Additionally, there are different programming languages and they could have different implementations of number limits. So you can imagine that specialized applications could handle much larger (and/or more exact/precise) numbers than C++.

1
  • This "answer" is incorrect: calculators use BCD number representation in order to avoid truncation errors. I.E. 0.1 decimal cannot be accurately represented as a finite length binary number.
    – sawdust
    Dec 22, 2015 at 8:31
5

In case you'd like a practical example of how many programs on a typical Linux system handle large number processing and output:

libgmp - The GNU Multiple Precision Arithmetic Library is the most widely used library for this purpose on Linux systems. A simple example of multiplying 2^80 by 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);

So basically it's the same as using the normal + - * / operators, just with a library to break the numbers up and store them internally as multiple machine word sized (i.e 32-bit) numbers. There are also scanf() type functions for handling converting text input to integer types.

The structure of mpz_t is exactly like Scott Chamberlain's example of counting to 6 using two hands. It's basically an array of machine word sized mp_limb_t types, and when a number is too large to fit in a machine word, GMP uses multiple mp_limb_t to store the high/low parts of the number.

5

In your mind you only know 10 different digits. 0 to 9. Internally in your brain, this is certainly encoded differently than in a computer.

A computer uses bits to encode numbers, but that is not important. That's just the way engineers chose to encode stuff, but you should ignore that. You can think of it as a 32 bit computer has a unique representation of more than 4 billion different values, while us humans have a unique representation for 10 different values.

Whenever we must comprehend a larger number, we use a system. The leftmost number is the most important. It is 10 times more important than the next.

A computer able to differentiate between four billion different values, will similarly have to make the leftmost value, in a set of values, be four billion times as important as the next value in that set. Actually a computer does not care at all. It does not assign "importance" to numbers. Programmers must make special code to take care of that.

Whenever a value becomes greater than the number of unique symbols, 9 in a humans mind, you add one to the number to the left.

3+3=6

In this case, the number still fits within a single "slot"

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

So humans always deal with the problem of not having enough unique symbols. Unless the computer has a system to deal with this, it would simply write 0, forgetting that there was a number extra. Luckily, computers have an "overflow flag" that is raised in this case.

987+321 is more difficult.

You may have learned a method in school. An algorithm. The algorithm is quite simple. Start by adding the two leftmost symbols.

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

Then you move to the next slot and perform the same addition.

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

Since we had an overflow, it means that we have to add 1 to the next number.

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

There are no more numbers to add, so we simply create a slot and inser 1 because the overflow flag was raised.

1308

A computer does it exactly the same way, except it has 2^32 or even better 2^64 different symbols, instead of only 10 like humans.

On a hardware level, the computer works on single bits using exactly the same method. Luckily, that is abstracted away for programmers. Bits is only two digits, because that is easy to represent in a power line. Either the light is on, or it is off.

Finally, a computer could display any number as a simple sequence of characters. That's what computers are best at. The algorithm for converting between a sequence of characters, and an internal representation is quite complex.

3
  • In my mind I know 36, but I typically only use 16 of them. Jan 13, 2014 at 21:00
  • 'A computer uses bits to encode numbers, but that is not important.' In the context of the user asking about 32 bit words and how they are used to store numbers larger than 2^32-1 is is very important.
    – RichieHH
    Jan 17, 2014 at 13:26
  • It is not important how you encode numbers in the memory of your brain. You've got a finite number of representations; most have learnt 10 different symbols. Inside your brain, this is probably represented in the form of thousands of neurons and synapses. In a computer it is represented in the form of electricity or no electricity on a power line. From a programming perspective - or when learning maths, it is not important at all, except in the rare case where you're programming directly for a specific set of CPUs. He is asking about 32 bit vs 64 bit, not individual bits.
    – frodeborli
    Jan 17, 2014 at 14:04
3

Because you are not displaying a number (as far as the computer is concerned), but a string, or a sequence of digits. Sure, some apps (like the calculator, I guess), which deal with numbers, can handle such a number, I guess. I don't know what tricks they use... I'm sure some of the other, more elaborate answers cover that.

0

Most of the content of this answer originally came from this answer (written before that other question was marked as a duplicate). So I discuss using 8-bit values (even though this question asked about 32-bit values), but that's okay because 8-bit values are simpler to understand conceptually, and the same concepts apply to larger values like 32-bit arithmetic.

When you add two numbers that are 8 bit, the biggest number you can get (0xFF + 0xFF = 1FE). In fact, if you multiply two numbers that are 8-bit, the biggest number you can get (0xFF * 0xFF = 0xFE01) is still 16 bits, twice of 8-bits.

Now, you may be assuming that an x-bit processor can only keep track of x-bits. (For example, an 8-bit processor can only keep track of 8 bits.) That's not accurate. The 8-bit processor receives data in 8-bit chunks. (These "chunks" typically have a formal term: a "word". On an 8-bit processor, 8-bit words are used. On a 64-bit processor, 64 bit words can be used.)

So, when you give the computer 3 bytes:
Byte #1: The MUL instruction
Byte #2: the high order bytes (e.g., 0xA5)
Byte #3: the lower order bytes (e.g., 0xCB)
The computer can generate a result that is more than 8 bits. The CPU may generate results like this:
0100 0000 0100 0010 xxxx xxxx xxxx xxxx 1101 0111
a.k.a.:
0x4082xxxxD7
Now, let me interpret that for you:
0x just means the following digits are hexadecimal.
I will discuss the "40" in more detail momentarily.
82 is part of the "A" register, which is a series of 8 bits.
xx and xx are part of two other registers, named the "B" register and the "C" register. The reason that I didn't fill those bits with zeros or ones is that an "ADD" instruction (sent to the CPU) may result in those bits being unchanged by the instruction (whereas most of the other bits I use in this example may get altered, except for some of the flag bits).
D7 would fit in more bits, called the "D" register.
A register is just a piece of memory. Registers are built into the CPUs, so the CPU can access registers without needing to interact with the memory on a RAM stick.

So the mathematical result of 0xA5 times 0xCB is 0x82D7.

Now, why did the bits get split into the A and D registers instead of the A and B registers, or the C and D registers? Well, once again, this is a sample scenario that I'm using, meant to be rather similar in concept to a real Assembly language (Intel x86 16-bit, as used by the Intel 8080 and 8088 and many newer CPUs). There might be some common rules, such as the "C" register typically being used as an index for counting operations (typical for loops), and the "B" register being used for keeping track of offsets that help to specify memory locations. So, "A" and "D" may be more common for some of the common arithmetic functions.

Each CPU instruction should have some documentation, used by people who program in Assembly. That documentation should specify what registers get used by each instruction. (So the choice about which registers to use is often specified by the designers of the CPU, not the Assembly language programmers. Although, there can be some flexibility.)

Now, getting back to the "40" in the above example: that is a series of bits, often called the "flags register". Each bit in the flags register has a name. For example, there is an "overflow" bit that the CPU may set if the resulting is bigger than the space that can store one byte of the results. (The "overflow" bit may often be referred to by the abbreviated name of "OF". That's a capital o, not a zero.) Software can check for the value of this flag and notice the "problem". Working with this bit is often handled invisibly by higher-level languages, so beginning programmers often don't learn about how to interact with the CPU flags. However, Assembly programmers may commonly access some of these flags in a way very similar to other variables.

For instance, you might have multiple ADD instructions. One ADD instruction might store 16 bits of results in the A register and the D register, while another instruction might just store the 8 low bits in the A register, ignore the D register, and specify the overflow bit. Then, later (after storing the results of the A register into main RAM), you could use another ADD instruction that stores just the 8 high bits in a register (possibly the A register.) Whether you would need to use an overflow flag may depend on just what multiplication instruction you use.

(There is also commonly an "underflow" flag, in case you subtract too much to fit in the desired result.)

Just to show you how complicated things got:
The Intel 4004 was a 4-bit CPU
The Intel 8008 was an 8-bit CPU. It had 8-bit registers named A, B, C, and D.
The Intel 8086 was a 16-bit CPU. It had 16-bit registers named AX, BX, CX, and DX.
The Intel 80386 was a 32-bit CPU. It had 32-bit registers named EAX, EBX, ECX, and EDX.
The Intel x64 CPUs have 64-bit registers named RAX, RBX, RCX, and RDX. The x64 chips can run 16-bit code (in some operating modes), and can interpret 16-bit instructions. When doing so, the bits that make up the AX register are half of the bits that make up the EAX register, which are half of the bits that make up the RAX register. So anytime you change the value of AX, you are also changing EAX and RAX, because those bits used by AX are part of the bits used by RAX. (If you change EAX by a value that is a multiple of 65,536, then the low 16 bits are unchanged so AX would not change. If you change EAX by a value that is not a multiple of 65,536, then that would affect AX as well.)

There are more flags and registers than just the ones that I've mentioned. I simply chose some commonly used ones to provide a simple conceptual example.

Now, if you're on an 8-bit CPU, when you write to memory, you may find some restrictions about being able to refer to an address of 8-bits, not an address of 4 bits or 16-bits. The details will vary based on the CPU, but if you have such restrictions, then the CPU may be dealing with 8-bit words, which is why the CPU is most commonly referred to as an "8-bit CPU".

1
  • I feel like pieces of my answer re-iterate some of the other answers to this question. However, this wasn't noticed when I first wrote the content since I wrote that for another question. Also, while I appreciate Animism's answer including some code in the C language, I felt my content provided some details about how Assembly works, which is closer to the CPU's actual actions/design. So my answer isn't trying to be the superior answer that is "better than" all the others, but just supplementary; adding another perspective with some additional insight
    – TOOGAM
    Dec 30, 2016 at 11:58

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .