Difference between signed and unsigned 16bit BCDs? - unsigned

How do you tell the difference?
For example, say you have 0110 0101 1001 0011.
The unsigned BCD is 6593, but what is the signed value?

Usually, you tell the difference by explicitly storing the sign.
Radix complement (en.wikipedia.org/wiki/Method_of_complements)

in normal binary system, signed numbers uses the MSB (most significant bit) to determine the sign of the number, the rest of the number is the actual value.
Unlike that in Packed BCD, the 4 LSb (least significant bits) represent the sign, and the rest (to the left) of the number represents the actual value.

Related

What makes the processor to know about unsigned and signed numbers?

If I talk about 2'complement, the MSB is used as a sign bit. For example in 8 bit 2'complement signed notation 01111111 is +127 and and 11111111 is -128. But on the contrary 11111111 is 255 in unsigned notation. How does the processor know if the number is signed or unsigned? Is there any other bit used for this purpose? Compiler makes something?
The beauty of 2's complement is that the bit operations for arithmetic operations are exactly equivalent to unsigned. So most likely, the processor doesn't give a monkeys.
The same cannot be said for 1's complement arithmetic (it requires, among other things, a complementing subtractor), or signed magnitude arithmetic.

How to tell if hex value is negative?

I have just learned how to read hexadecimal values. Until now, I was only reading them as positive numbers. I heard you could also write negative hex values.
My issue is that I can't tell if a value is negative or positive.
I found a few explanations here and there but if I try to verify them by using online hex to decimal converters, they always give me different results.
Sources I found:
https://stackoverflow.com/a/5827491/5016201
https://coderanch.com/t/246080/java-programmer-OCPJP/certification/Negative-Hexadecimal-number
If I understand correctly it means that: If a hex value written with all its bits having something > 7 as its first hex digit, it is negative.
All 'F' at the beginning or the first digit means is that the value is negative, it is not calculated.
For exemple if the hex value is written in 32 bits:
FFFFF63C => negative ( -2500 ?)
844fc0bb => negative ( -196099909 ?)
F44fc0bb => negative ( -196099909 ?)
FFFFFFFF => negative ( -1 ?)
7FFFFFFF => positive
Am I correct? If not, could you tell me what I am not getting right?
Read up on Two's complement representation: https://en.wikipedia.org/wiki/Two%27s_complement
I think that the easiest way to understand how negative numbers (usually) are treated is to write down a small binary number and then figure out how to do subtraction by one. When you reach 0 and apply that method once again - you'll see that you suddenly get all 1's. And that is how "-1" is (usually) represented: all ones in binary or all f's in hexadecimal. Commonly, if you work with signed numbers, they are represented by the first (most significant) bit being one. That is to say that if you work with a number of bits that is a multiple of four, then a number is negative if the first hexadecimal digit is 8,9,A,B,C,D,E or F.
The method to do negation is:
invert all the bits
add 1
Another benefit from this representation (two's complement) is that you only get one representation for zero, which would not be the case if you marked signed numbers by setting the MSB or just inverting them.
From what I understand, you always need to look at the left-most digit to tell the sign. If in hex, then anything from 0-7 is positive and 8-f is negative. Alternatively, you can convert from hex to binary, and if there's a 1 in the left-most digit, then the number is negative.
HEX <-> BINARY <-> SIGN
0-7 <-> 0000-0111 <-> pos
8-F <-> 1000-1111 <-> neg
The answer here in the forum looks good:
Each hexadecimal "digit" is 4 bits. The d in the high order position
is 1101. So you see it's got a high bit of one, therefore the whole
number is negative.
and
A hex number is always positive (unless you specifically put a minus
sign in front of it). It might be interpreted as a negative number
once you store it in a particular data type. Only then does the most
significant bit (MSB) matter, but it's the MSB of the number "as
stored in that data type". In that respect the answers above are only
partially correct: only in the context of an actual data type (like an
int or a long) does the MSB matter.
If you store "0xdcafe" in an int, the representation of it would be
"0000 0000 0000 1101 1100 1010 1111 1110" - the MSB is 0. Whereas the
representation of "0xdeadcafe" is "1101 1110 1010 1101 1100 1010 1111
1110" - the MSB is 1.
You can tell whether a hexadecimal integer is positive or negative by inspecting its most significant (highest) digit. If the digit is ≥ 8, the number is negative; if the digit is ≤ 7, the number is positive. For example, hexadecimal 8A20 is negative and 7FD9 is positive

Arduino Arithmetic error negative result

I am trying to times 52 by 1000 and i am getting a negative result
int getNewSum = 52 * 1000;
but the following code is ouputting a negative result: -13536
An explanation of how two's complement representation works is probably better given on Wikipedia and other places than here. What I'll do here is to take you through the workings of your exact example.
The int type on your Arduino is represented using sixteen bits, in a two's complement representation (bear in mind that other Arduinos use 32 bits for it, but yours is using 16.) This means that both positive and negative numbers can be stored in those 16 bits, and if the leftmost bit is set, the number is considered negative.
What's happening is that you're overflowing the number of bits you can use to store a positive number, and (accidentally, as far as you're concerned) setting the sign bit, thus indicating that the number is negative.
In 16 bits on your Arduino, decimal 52 would be represented in binary as:
0000 0000 0011 0100
(2^5 + 2^4 + 2^2 = 52)
However, the result of multiplying 52 by 1,000 -- 52,000 -- will end up overflowing the magnitude bits of an int, putting a '1' in the sign bit on the end:
*----This is the sign bit. It's now 1, so the number is considered negative.
1100 1011 0010 0000
(typically, computer integer arithmetic and associated programming languages don't protect you against doing things like this, for a variety of reasons, mostly related to efficiency, and mostly now historical.)
Because that sign bit on the left-hand end is set, to convert that number back into decimal from its assumed two's complement representation, we assume it's a negative number, and then first take the one's complement (flipping all the bits):
0011 0100 1101 1111
-- which represents 13,535 -- and add one to it, yielding 13,536, and call it negative: -13,536, the value you're seeing.
If you read up on two's complement/integer representations in general, you'll get the hang of it.
In the meantime, this probably means you should be looking for a bigger type to store your number. Arduino has unsigned integers, and a long type, which will use four bytes to store your numbers, giving you a range from -2,147,483,648 to 2,147,483,647. If that's enough for you, you should probably just switch to use long instead of int.
Matt's answer is already a very good in depth explanation of what's happening, but for those looking for a more TL;dr practical answer:
Problem:
This happens quite often for Arduino programmers when they try to assign (= equal sign) the result of an arithmetic (usually multiplication) to a normal integer (int). As mentioned, when the result is bigger than the memory size compiler has assigned to the variables, overflowing happens.
Solution 1:
The easiest solution is to replace the int type with a bigger datatype considering your needs. As this tutorialspoint.com tutorial has explained there are different integer types we can use:
int:
16 bit: from -32,768 to 32,767
32 bit: from -2,147,483,648 to 2,147,483,647
unsigned int: from 0 to 65,535
long: from 2,147,483,648 to 2,147,483,647
unsigned long: from 0 to 4,294,967,295
Solution 2:
This works only if you have some divisions with big enough denominators, in your arithmetic. In Arduino compiler multiplication is calculated prior to the division. so if you have some divisions in your equation try to encapsulate them with parentheses. for example if you have a * b / c replace it with a * (b / c).

Two's Complement -- How are negative numbers handled?

It is my understanding that numbers are negated using the two's compliment, which to my understanding is: !num + 1.
So my question is does this mean that, for variable 'foo'=1, a negated 'foo' will be the exactly the same as variable 'bar'=255.
f we were to check if -'foo' == 'bar' or if -'foo' == 255, would we get that they are equal?
I know that some languages, such as Java, keep a sign bit -- so the comparisons would yield false. What of languages that do not? And I'm assuming that assembler/native machine does not have a sign bit.
In addition to all of this, I read about a zero flag or a carry-over flag that is set when a 'negative' number is added to another (of any sign) number. This flag being set whenever it is added because of the way two's complement works, 0x01 + 0xff = 0x00 (with the leading 1 truncated). What exactly is this flag used for?
And my last question, for other math operations (such as multiplication), would I have to re-negate the number (so it is now positive), perform the operation, and negate the result? E.g., !((!neg + 1) * pos) + 1.
Edit
Finished the question, so feel free fire away.
Yes, in two’s complement, the number x is represented as ~x+1, where ~x is the bitwise complement of the binary numeral for x in some fixed number bits. E.g., for eight bits, the binary numeral for x is 000000001, so the bitwise complement is 11111110, and adding one produces 11111111.
There is no way to distinguish -1 in eight-bit two’s complement from 255 in eight-bit binary (with no sign). They both have the same representation in bits: 11111111. If you are using both of these numbers, you must either separately remember which one is eight-bit two’s complement and which one is plain eight-bit binary or you must use more than eight bits. In other words, at the raw bit level, 11111111 is just eight bits; it has no value until we decide how to interpret it.
Java and typical other languages do not maintain a sign bit separate from the value of a number; the sign is part of the encoding of the number. Also, typical languages do not allow you to compare different types. If you have a two’s complement x and an unsigned y, then either one must be converted to the type of the other before comparison or they must both be converted to a third type. Thus, if you compare x and y, and one is converted to the other, then the conversion will overflow or wrap, and you cannot expect to get the correct mathematical result. To compare these two numbers, we might convert each of them to a wider integer, such as 32-bits, then compare. Converting the eight-bit two’s complement 11111111 to a 32-bit integer produces -1, and converting the eight-bit plain binary 11111111 to a 32-bit integer produces 255, and then the comparison reports they are unequal.
The zero flag and the carry flag you read about are flags that are set when a comparison instruction is executed in a computer processor. Most high-level languages do not give you direct access to these flags. Many processors have an instruction with a form like this:
cmp a, b
That instruction subtracts b from a and discards the difference but remembers several flags that describe the subtraction: Was the result zero (zero flag)? Did a borrow occur (borrow flag)? Was the result negative (sign flag)? Did an overflow occur (overflow flag)?
The compare instruction requires that the two things being compared be the same type (two’s complement or unsigned), but it does not care which type. The results can be tested later by checking particular combinations of the flags depending on the type. That is, the information recorded in the flags can distinguish whether one two’s complement number was greater than another or whether one unsigned number was greater than another, depending on what tests are made. There are conditional branch instructions that test the desired flag properties.
There is generally no need to “un-negate” a number to perform arithmetic operations. Processors include arithmetic instructions that work on two’s complement numbers. Usually the add and subtract instructions are type-agnostic, the same way the compare instruction is, but the multiply and divide instructions are not (except for some forms of multiply that return partial results). The add and subtract instructions can be type-agnostic because the wrapping that occurs in the arithmetic works for both two’s complement and unsigned. However, that wrapping does not work for multiplication and division.

integer stored as float

I have some questions regarding integers and floats:
Can I store every 32-bit unsigned integer value into a 64-bit IEEE floating point value (such that when I assign the double value back to an int the int will contain the original value)?
What are the smallest (magnitude wise) positive and negative integer values that cannot be stored in a 32-bit IEEE floating point value (by the same definition as in 1)?
Do the answers to these questions depend on language used?
//edit: I know these questions sound a bit like from some test but I'm asking about these things because I need to make some decisions on a dataformat definition
Yes, you can store a 32-bit integer a 64-bit double without information loss. The mantissa has 53 bits of precision, which is enough.
A 32-bit float has a 24-bit mantissa, so the maximum and minimum integers with a unique representation are 2^24-1 and -2^24+1 (16777215 and -16777215). Greater numbers don't have a unique representation; for example 16777216 == (float)16777217.
If you assume the language follows IEEE-754, it doesn't depend on the language.

Resources