addition of "binary" numbers - c

What is the result of adding the binary numbers 01000001 and 11111111 on an 8 bit machine?

If we are supposed to interpret this with the rules of C (it is tagged as such), for the signed case there are three interpretations of these numbers possible, corresponding to the three sign representations that are allowed in C.
For the unsigned case the standard requires that unsigned arithmetic wraps silently. All computation is done modulo 256 in that case.

Integer overflow.
If the numbers are unsigned (i.e. modular), 0100000 (with modular 8-bit math, addition of 11111111 is equal to subtraction of 1).

If both values are unsigned, then the result is 320 in decimal. Both operands are promoted to int before the addition, and int is required by the standard to have at least 16 bits, even on an 8 bit machine. The question doesn't make any restrictions for the result.

Unless you want the "wrong result fast", the answer is 320.
Correctly adding two numbers (in whatever representation) anywhere (including 8-bit machines) results in a unique number that can be represented in a multitude of different ways.
320 can be represented as 320 (usual decimal (base-10) representation) or 101000000 (binary representation) or 253413120100 (factoradic), ...

I think you just add the numbers, then cut the overflowing bits (from the left)

if it's only 8 bit, the maximum you can have is 255 (1111 1111) if the value is unsigned and 127 if it is signed (-128 being the lowest). Therefore, doing this addition will cause overflow, which goes back to 0 and then keeps counting. Think of it as your car miles meter: if there can only be, say, 8 digits on the counter, and your counter is at 99 999 999 miles, if you add one more, the counter will go back to 0.

If these are signed integers, they represent 65 and -128 -1. Adding them will give -63 64.
If these are unsigned integers, they represent 65 and 255. Since the sum can not be represented in 8 bits, the result will be 64 and the overflow bit will be set.

Related

why 10000101 is both -5 and 133 [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
Vidoe
00000101 is 5
10000101 is -5
but 10000101 is also 133
I don't understand why 1 binary is able to represent 2 numbers.
Any help is appreciated, thank you.
The word “Gift” has at least two meanings. In English, it means a present you give somebody. In German, it means poison. To know which concept a speaker means, you must know which language they are speaking.
The bit string 10000101 does not mean anything by itself. It is just some bits. Bit strings have values only when we associate them with types, which are (in part) methods of associating values with bit strings. To know what value it represents, you must know which type it is being used with.
If we interpret 10000101 as a pure binary numeral, it means 1•27 + 1•22 + 1•20 = 128 + 4 + 1 = 133.
If we interpret 10000101 as a sign-and-magnitude representation, it means negative with 1•22 + 1•20 = − (4+1) = −5.
If we interpret 10000101 as a two’s complement representation, it means −1•27 + 1•22 + 1•20 = −128 + 4 + 1 =  −123.
In C, every declared object and every constant has a type, and every expression built from these things has a type. The type says how to interpret the bits.
In these representations of a signed number that occupies one byte
00000101 is 5
10000101 is -5
the most significant bit is the sign bit that determines whether the stored number is positive or negative.
That is if the sign bit is set then the corresponding value stored in value bits is negated.
This representation of signed values is named like sign and magnitude.
It is implementation-defined how signed values are stored. Most computer architectures use the so called 2's complement representation. For such an architecture the negative number -5 is represented like
11111011 is -5
If the number is considered as having an unsigned integer type then no bit is allocated as the sign bit. In this case all bits are value bits. So for unsigned integer this representation 10000101 yields the value 133.
I don't understand why 1 binary is able to represent 2 numbers.
Pure binary numbers have no sign.
So as pure binary, 10000101 is unambiguously 133, pure and simple.
But, of course, we want to be able to handle negative numbers. So there are various ways of rigging things up so that some bit patterns represent negative numbers. But as soon as you do that, you're going to end up with bit patterns which can be interpreted two ways: as straight binary (giving a positive number) or as signed binary (giving a negative number). Any bit pattern that represents a negative number can also be interpreted as a positive number, by just not using whatever negative-number rule you were using.
Here's another way of thinking about it. Consider the word "march". It's the thing that bands do in parades. But if I capitalize the first letter, March, it's the third month of the year. So If I write "March", and I pay attention to the capitalization, it's a month, but if I ignore the capitalization, it's a verb.
Similarly, if I write 10000101, and I ignore the possibility of signedness, I get 133.
But if I pay attention to sign, I get a negative number.
Or if I interpret it as a character, I might get something else!
Here are 5 possibilities:
bit pattern
interpreted as
gives
10000101
pure binary
133
10000101
sign/magnitude
-5
10000101
ones' complement
-122
10000101
two's complement
-123
10000101
character
à
(Now, I confess, in the last row I had to cheat, by using the old MS-DOS character set. In Unicode, 10000101 does not represent a character, and in the Windows character set, it's one character that's an ellipsis, or three dots: … .)
Now, one thing you may be worried about is whether we're getting "something for nothing", by having a bit pattern that can do double duty as either as positive or a negative number. Are we cheating and extending the range somehow? The answer is that, no, we're not. Let's stay with 8-bit numbers. If we treat our 8-bit numbers as pure binary, we can cover the range from 0 to 255 (that is, 00000000 to 11111111). We can't represent the number 300, because it takes too many bits, and we can't represent the number -5, because we have no way to represent negative numbers. With 8 bits, in pure binary, we can represent only 0 to 255, and that's it.
If we switch to two's complement, we can represent any number from -128 to +127 — which is exactly 256 different numbers. We still can't represent 300 (positive or negative), because it's still too many bits. But, now, we can't represent the number 200, either, because if we try to, it's 11001000, and that's the two's complement bit pattern for -56. Similarly, we can't represent 133 (your original example), because its bit pattern is 10000101, and that's a negative number, too, -123.

If a C signed integer type is stored in 22 bits, what is the smallest value it can store?

I am learning about data allocation and am a little confused.
If you are looking for the smallest or greatest value that can be stored in a certain number of bits then does it matter what the data type is?
Wouldn't the smallest or biggest number that could be stored in 22 bits would be 22 1's positive or negative? Is the first part of this question a red herring? Wouldn't the smallest value be -4194303?
A 22-bit data element can store any one of 2^22 distinct values. What those values actually mean is a matter of interpretation. That interpretation may be imposed by a compiler or some piece of hardware, or may be under the control of the programmer, and suit some specific application.
A simple interpretation, of course, would be to treat the 22 bits as an unsigned integer, with values from 0 to (2^22)-1. A two's-complement, signed integer is a slightly more sophisticated interpretation of the same bits. Or you (or the compiler, or CPU) could divide the 22 bits up into a mantissa and exponent, and store a range of decimal numbers. The range and precision would depend on how many bits were allocated to the mantissa, and how many to the exponent.
Or you could split the bits up and use some for the numerator and some for the denominator of a fraction. Or, in fact, anything else.
Some of these interpretations of the bits are built into hardware, some are implemented by compilers or libraries, and some are entirely under the programmer's control. Not all programming languages allow the programmer to manipulate individual bits in a natural or efficient way, but some do. Sometimes, using a highly unconventional interpretation of binary data can give significant efficiency gains, but usually at the expense of readability and maintainability.
So, yes, it matters what the data type is.
There is no law (of humans, logic, or nature) that says bits must represent numbers only in the pattern that one of the bits represents 20, another represents 21, another represents 22, and so on (and the number represented is the sum of those values for the bits that are 1). We have choices about how to use bits to represent numbers, including:
The bits do use that pattern, and so 22 bits can represent any number from 0 to the sum of 20 + 21 + 22 + … + 221 = 222 − 1 = 4,194,303. The smallest representable value is 0.
The bits mostly use that pattern, but it is modified so that one bit represents −221 instead of +221. This is called two’s complement, and the smallest value representable is −221 = −2,097,152.
The bits represent numbers as described above except the represent value is divided by 1000. This is called fixed-point. In the first case, the value represent by all bits 1 would be 4194.303, but the smallest representable value would be 0. With a combination of two’s complement and fixed-point scaled by 1/1000, the smallest representable value would be −2097.152.
The bits represent a floating-point number, where one bit represents a sign (+ or −), certain bits represent an exponent and other information, and the remaining bits represent a significand. In common floating-point formats, when all the bits in that exponent-and-other field are 1s and the significand field bits are 0s, the number represents +∞ or −∞, according to the sign bit. In such a format, the smallest representable value is −∞.
As an example, we could designate patterns of bits to represent numbers arbitrarily. We could say that 0000000000000000000000 represents 34, 0000000000000000000001 represents −15, 0000000000000000000010 represents 5, 0000000000000000000011 represents 3+4i, and so on. The smallest representable value would be whichever of those arbitrary values is smallest.
So what the smallest representable value is depends entirely on the type, since the “type” of the data includes the scheme by which the bits represent values.
If the type is a “signed integer type,” there is still some flexibility in the representation. Most modern C implementations (and other programming languages) use the two’s complement scheme described above. But the C standard still allows two other schemes:
One’s complement: If the first bit is 1, the value represented is negative, and its magnitude is given by complementing the remaining bits and interpreting them as binary. Using six bits for an example, 101001 would be negative with the magnitude of 101102 = 22, so −22.
Sign-and-magnitude: If the first bit is 1, the value represented is negative, and its magnitude is given by interpreting the remaining bits as binary. Using the same bits, 101001 would negative with the magnitude of 010012 = 9, so −9.
In both one’s complement and sign-and-magnitude, the smallest representable value with 22 bits is −(221−1) = −2,097,151.
To stretch the question further, C defines standard integer types but allows implementations to extend the language. An implementation could define some “signed integer type” with an arbitrary scheme for representing numbers, as long as that scheme included a sign, to make the name correct.
Without going into technical jargon about doing maths with Two's compliment, I'll try to explain in easy words.
First you need to raise 2 with power of 'number of bits'.
Let's take an example of an 8 bit type,
An un-signed 8-bit integer can store 2 ^ 8 = 256 values.
Since values are indexed starting from 0, so values range from 0 - 255.
Assuming you want to store signed values, so you need to get the half (simply divide it by 2),
256 / 2 = 128.
Remember we start from zero,
You might be rightly thinking you can store -127 to 127 starting from zero on both sides.
Just know that there is only zero (there is nothing like +0 or -0),
so you start with zero to positive half. 0 to 127,
that leaves you with negative half starting from -1 to -128
Hence the range will be -128 to 127.
For a 22 bit signed integer you can do the math,
2 ^ 22 = 4,194,304
4194304 / 2 = 2,097,152
-1 for positive side,
range will be, -2097152 to 2097151.
To answer your question,
-2097152 would be the smallest number you can store.
Thanks everyone for the replies. I figured it out with the help of all of your info but I will explain the answer to show exactly what gaps of knowledge I had that lead to my misunderstanding.
The data type does matter in this question because for signed data types the first bit is used to represent whether or not a binary number is positive or negative. 0111 = 7 and 1111 = -7
sign int and unsigned int use the same number of bits, 32 bits. Since an unsigned int is unsigned: the first bit isn't used to represent positive or negative so it can represent a larger number with that extra bit. 1111 converted to an unsigned int is 15 whereas with the signed int it was -7 since the furthest left bit represents the sign: 1 is negative and 0 is positive.
Now to answer "If a C signed integer type is stored in 22 bits, what is the smallest value it can store?":
If you convert binary to decimal you get 1111111111111111111111 = 4194304
This decimal value -1 is the maximum value an unsigned could hold. Since our data type is signed it has to use one less bit for the number value since the first bit represents the sign. This gives us -2097152.
Thanks again, everyone.

What does signed and unsigned values mean?

What does signed mean in C? I have this table to show:
This says signed char 128 to +127. 128 is also a positive integer, so how can this be something like +128 to +127? Or do 128 and +127 have different meanings? I am referring to the book Apress Beginning C.
A signed integer can represent negative numbers; unsigned cannot.
Signed integers have undefined behavior if they overflow, while unsigned integers wrap around using modulo.
Note that that table is incorrect. First off, it's missing the - signs (such as -128 to +127). Second, the standard does not guarantee that those types must fall within those ranges.
By default, numerical values in C are signed, which means they can be both negative and positive. Unsigned values on the other hand, don't allow negative numbers.
Because it's all just about memory, in the end all the numerical values are stored in binary. A 32 bit unsigned integer can contain values from all binary 0s to all binary 1s. When it comes to 32 bit signed integer, it means one of its bits (most significant) is a flag, which marks the value to be positive or negative. So, it's the interpretation issue, which tells that value is signed.
Positive signed values are stored the same way as unsigned values, but negative numbers are stored using two's complement method.
If you want to write negative value in binary, first write positive number, next invert all the bits and last add 1. When a negative value in two's complement is added to a positive number of the same magnitude, the result will be 0.
In the example below lets deal with 8-bit numbers, because it'll be simple to inspect:
positive 95: 01011111
negative 95: 10100000 + 1 = 10100001 [positive 161]
0: 01011111 + 10100001 = 100000000
^
|_______ as we're dealing with 8bit numbers,
the 8 bits which means results in 0
The table is missing the minuses. The range of signed char is -128 to +127; likewise for the other types on the table.
It was a typo in the book; signed char goes from -128 to 127.
Signed integers are stored using the two's complement representation, in which the first bit is used to indicate the sign.
In C, chars are just 8 bit integers. This means that they can go from -(2^7) to 2^7 - 1. That's because we use the 7 last bits for the number and the first bit for the sign. 0 means positive and 1 means negative (in two's complement representation).
The biggest positive 7 bit number is (01111111)b = 2^7 - 1 = 127.
The smallest negative 7 bit number is (11111111)b = -128
(because 11111111 is the two's complement of 10000000 = 2^7 = 128).
Unsigned chars don't have signs so they can use all the 8 bits. Going from (00000000)b = 0 to (11111111)b = 255.
Signed numbers are those that have either + or - appended with them.
E.g +2 and -6 are signed numbers.
Signed Numbers can store both positive and negative numbers thats why they have bigger range.
i.e -32768 to 32767
Unsigned numbers are simply numbers with no sign with them. they are always positive. and their range is from 0 to 65535.
Hope it helps
Signed usually means the number has a + or - symbol in front of it. This means that unsigned int, unsigned shorts, etc cannot be negative.
Nobody mentioned this, but range of int in table is wrong:
it is
-2^(31) to 2^(31)-1
i.e.,
-2,147,483,648 to 2,147,483,647
A signed integer can have both negative and positive values. While a unsigned integer can only have positive values.
For signed integers using two's complement , which is most commonly used, the range is (depending on the bit width of the integer):
char s -> range -128-127
Where a unsigned char have the range:
unsigned char s -> range 0-255
First, your table is wrong... negative numbers are missing. Refering to the type char.... you can represent at all 256 possibilities as char has one byte means 2^8. So now you have two alternatives to set ur range. either from -128 to +128 or 0 to 255. The first one is a signed char the second a unsigned char. If you using integers be aware what kind of operation system u are using. 16 bit ,32 bit or 64 bit. Int (16 bit,32 bit,64 bit). char has always just 8 bit value.
It means that there will likely be a sign ( a symbol) in front of your value (+12345 || -12345 )

What are the max and min numbers a short type can store in C?

I'm having a hard time grasping data types in C. I'm going through a C book and one of the challenges asks what the maximum and minimum number a short can store.
Using sizeof(short); I can see that a short consumes 2 bytes. That means it's 16 bits, which means two numbers since it takes 8 bits to store the binary representation of a number. For example, 9 would be 00111001 which fills up one bit. So would it not be 0 to 99 for unsigned, and -9 to 9 signed?
I know I'm wrong, but I'm not sure why. It says here the maximum is (-)32,767 for signed, and 65,535 for unsigned.
short int, 2 Bytes, 16 Bits, -32,768 -> +32,767 Range (16kb)
Think in decimal for a second. If you have only 2 digits for a number, that means you can store from 00 to 99 in them. If you have 4 digits, that range becomes 0000 to 9999.
A binary number is similar to decimal, except the digits can be only 0 and 1, instead of 0, 1, 2, 3, ..., 9.
If you have a number like this:
01011101
This is:
0*128 + 1*64 + 0*32 + 1*16 + 1*8 + 1*4 + 0*2 + 1*1 = 93
So as you can see, you can store bigger values than 9 in one byte. In an unsigned 8-bit number, you can actually store values from 00000000 to 11111111, which is 255 in decimal.
In a 2-byte number, this range becomes from 00000000 00000000 to 11111111 11111111 which happens to be 65535.
Your statement "it takes 8 bits to store the binary representation of a number" is like saying "it takes 8 digits to store the decimal representation of a number", which is not correct. For example the number 12345678901234567890 has more than 8 digits. In the same way, you cannot fit all numbers in 8 bits, but only 256 of them. That's why you get 2-byte (short), 4-byte (int) and 8-byte (long long) numbers. In truth, if you need even higher range of numbers, you would need to use a library.
As long as negative numbers are concerned, in a 2's-complement computer, they are just a convention to use the higher half of the range as negative values. This means the numbers that have a 1 on the left side are considered negative.
Nevertheless, these numbers are congruent modulo 256 (modulo 2^n if n bits) to their positive value as the number really suggests. For example the number 11111111 is 255 if unsigned, and -1 if signed which are congruent modulo 256.
The reference you read is correct. At least, for the usual C implementations where short is 16 bits - that's not actually fixed in the standard.
16 bits can hold 2^16 possible bit patterns, that's 65536 possibilities. Signed shorts are -32768 to 32767, unsigned shorts are 0 to 65535.
This is defined in <limits.h>, and is SHRT_MIN & SHRT_MAX.
Others have posted pretty good solutions for you, but I don't think they have followed your thinking and explained where you were wrong. I will try.
I can see that a short consumes 2 bytes. That means it's 16 bits,
Up to this point you are correct (though short is not guaranteed to be 2 bytes long like int is not guaranteed to be 4 — the only guaranteed size by standard (if I remember correctly) is char which should always be 1 byte wide).
which means two numbers since it takes 8 bits to store the binary representation of a number.
From here you started to drift a bit. It doesn't really take 8 bits to store a number. Depending on a number, it may take 16, 32 64 or even more bits to store it. Dividing your 16 bits into 2 is wrong. If not a CPU implementation specifics, we could have had, for example, 2 bit numbers. In that case, those two bits could store values like:
00 - 0 in decimal
01 - 1 in decimal
10 - 2 in decimal
11 - 3 in decimal
To store 4, we need 3 bits. And so the value would "not fit" causing an overflow. Same applies to 16-bit number. For example, say we have unsigned "255" in decimal stored in 16-bits, the binary representation would be 0000000011111111. When you add 1 to that number, it becomes 0000000100000000 (256 in decimal). So if you had only 8 bits, it would overflow and become 0 because the most significant bit would have been discarded.
Now, the maximum unsigned number you can in 16 bits memory is — 1111111111111111, which is 65535 in decimal. In other words, for unsigned numbers - set all bits to 1 and that will yield you the maximum possible value.
For signed numbers, however, the most significant bit represents a sign — 0 for positive and 1 for negative. For negative, the maximum value is 1000000000000000, which is -32678 in base 10. The rules for signed binary representation are well described here.
Hope it helps!
The formula to find the range of any unsigned binary represented number:
2 ^ (sizeof(type)*8)

Range of signed char

Why the range of signed character is -128 to 127 but not -127 to 128 ?
That is because of the way two's complement encoding works: 0 is treated as a "positive" number (signed bit off), so, therefore, the number of available positive values is reduced by one.
In ones' complement encoding (which is not very common nowadays, but in the olden days, it was), there were separate values for +0 and -0, and so the range for an 8-bit quantity is -127 to +127.
In 8-bit 2's complement encoding numbers -128 and +128 have the same representation: 10000000. So, the designer of the hardware is presented with an obvious dilemma: how to interpret bit-pattern 10000000. Formally, it will work either way. If they decide to interpret it as +128, the resultant range will be -127..+128. If they decide to interpret it as -128, the resultant range will be -128..+127.
In actual real-life 2's complement representation the latter approach is chosen because it satisfies the following nice convention: all bit-patterns with 1 in higher-order bit represent negative numbers.
It is worth noting though, that language specification does not require 2's-complement implementations to treat the 100...0 bit pattern as a valid value in any signed integer type. E.g. implementations are allowed to restrict 8-bit signed char to -127..+127 range and regard 10000000 as an invalid bit combination (trap representation).
I think an easy way to explain this for the common soul is :
A bit is a value 0 or 1, or 2 possibilities
A 2-bit holds two combinations or 0 and 1 for four possible values : 00, 01, 10, and 11.
A 3-bit holds three combinations for a total of eight possible values : 000 to 111.
Thus n-bits holds n combinations for a total of 2^n possible values. Therefore, an 8-bit value is 2^8 = 256 possible values.
For signed numbers, the most significant bit (the first one reading the value from left to right) is the sign bit; that leaves a possibility of 2^(n-1) possible values. For an 8-bit signed number, this is 2^7 = 128 possible values for each sign. But since the positive sign includes the zero (0 to 127 = 128 different values, and 128 + 128 = 2^8 = 256), the negative sign includes -1 to... -128 for 128 different values also. Where :
10000000 = -128
...
11111111 = -1
00000000 = 0
...
01111111 = 127
#include <limits.h>
#include <stdio.h>
...
printf("range of signed character is %i ... %i", CHAR_MIN, CHAR_MAX );
If you just consider twos complement as arithmetic modulo 256, then the cutoff between positive and negative is purely arbitrary. You could just as well have put it at 63/-192, 254/-1, 130/-125, or anywhere else. However, as a standard signed integer format, twos complement came by convention put put the cutoff at 127/-128. This cutoff has one big benefit: the high bit being set corresponds directly to the number being negative.
As for the C language, it leaves the format of signed numbers up to the implementation, but only offers 3 choices of implementation, all of which use a "sign bit": sign/magnitude, ones complement, and twos complement.
If you look at ranges of chars and ints there seems to be one extra number on the negative side. This is because a negative number is always stored as 2’s compliment of its binary. For example, let us see how -128 is stored. Firstly, binary of 128 is calculated (10000000), then its 1’s compliment is obtained (01111111). A 1’s compliment is obtained by changing all 0s to 1s and 1s to 0s. Finally, 2’s compliment of this number, i.e. 10000000, gets stored. A 2’s compliment is obtained by adding 1 to the 1’s compliment. Thus, for -128, 10000000 gets stored. This is an 8-bit number and it can be easily accommodated in a char. As against this, +128 cannot be stored in a char because its binary 010000000 (left-most 0 is for positive sign) is a 9-bit number. However +127 can be stored as its binary 01111111 turns out to be a 8-bit number.
Step 1:
If you take 2's complement of any number from 0 up to 127 the bit number 8 will always be 1. So lets reserve that info.
Step2 :
if you find the -127 by applying 2's complement into +127 you will find "1 0 0 0 0 0 0 1" and finally if you substract 1 from this number then the smallest 8 bit number -128 will be achieved as "1 0 0 0 0 0 0 0"
As a result if we combine the info that we reserved at step 1 and the result from step2, we come to the conclusion that, the most significiant bit or bit number 8 in char containers must always be 1 so called signed bit.

Resources