Understanding & identifying signed numbers - hex

I'm new to this subject and I'm struggling to comprehend how 0xFFFFFFF & 0x00000001 can have the same sign, yet 0x0000001 and 0x12345678 have different signs. Based on my understanding thus far, hex digits that have the most significant bit between 0-7 are positive & 8-F are negative.
For further context, here is the thing I was trying to understand:
Question: Complete the C function that performs the operations and meets the requirements indicated in the comments.
Comments:
/*
* diffSign – return 1 if x and y have different signs
* Examples: diffSign(0xFFFFFFF, 0x00000001) = 0
* diffSign(0x0000001, 0x12345678) = 1
* Legal ops: & | ^ ~ << >>
* 1-byte const (0x00 to 0xFF)
*/
Answer:
int diffSign(int x, int y) {
return ((x >> 31) & 0x1) ^ ((y >> 31) & 0x1);
}
If possible, I would also greatly appreciate some clarification on how & 0x1 would help me to identify the sign! It seems rather redundant and I'm not too sure about the significance of that in the equation.

If you look closely, it makes perfect sense, just that you are not seeing that the most significant byte of 0xFFFFFFF is actually 0 because there are 7 F's.
0xFFFFFFF = 0x0FFF FFFF
which for a 32 bit integer represents a positive number.
However 0x0000001 and 0x12345678 do also have the same sign. Because what makes the difference is the most significant BIT. You are right that numbers with the most significant BYTE between 0-7 are positive, and 8-F negative. The comment in the function is wrong.
The code however is right, because it does 31 shifts to the right, leaving only the most significant BIT on each of the arguments (the sign bit of each argument) and does an XOR, which returns true only if both are not the same.

Related

Simple subtraction in Verilog

I've been working on a hex calculator for a while, but seem to be stuck on the subtraction portion, particularly when B>A. I'm trying to simply subtract two positive integers and display the result. It works fine for A>B and A=B. So far I'm able use two 7-segment displays to show the integers to be subtracted and I get the proper difference as long as A>=B
When B>A I see a pattern that I'm not able to debug because of my limited knowledge in Verilog case/if-else statements. Forgive me if I'm not explaining the best way but what I'm observing is that once the first number, A, "reaches" 0 (after being subtracted from) it loops back to F. The remainder of B is then subtracted from F rather than 0.
For example: If A=1, B=3
A - B =
1 - 1 = 0
0 - 1 = F
F - 1 = E
Another example could be 4-8=C
Below are the important snippets of code I've put together thus far.
First, my subtraction statement
always#*
begin
begin
Cout1 = 7'b1000000; //0
end
case(PrintDifference[3:0])
4'b0000 : Cout0 = 7'b1000000; //0
4'b0001 : Cout0 = 7'b1111001; //1
...
4'b1110 : Cout0 = 7'b0000110; //E
4'b1111 : Cout0 = 7'b0001110; //F
endcase
end
My subtraction is pretty straightforward
output [4:0]Difference;
output [4:0] PrintDifference;
assign PrintDifference = A-B;
I was thinking I could just do something like
if A>=B, Difference = B-A
else, Difference = A-B
Thank you everyone in advance!
This is expected behaviour of twos complement addition / subtraction which I would recommend reading up on since it is so essential.
The result obtained can be changed back into an unsigned form by inverting all the bits and adding one. Checking the most significant bit will tell you if the number is negative or not.

Understanding Adruino Binary to Decimal Conversations

I was looking at some code today for integrating a real time clock with an arduino and it had some binary to decimal (and vice versa) that I don't fully understand.
The code in question is below:
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
ex: decToBcd(12);
I really fail to grasp how this works. I am not sure I understand the math, or if some sort of assumptions are being taken advantage of.
Would someone mind explaining how exactly the math and data types below are supposed to work? If possible touching on why the value "16" is used in the conversions instead of "8" when we are supposed to be working with a byte value.
For context, the full code can be found here: http://www.codingcolor.com/microcontrollers/an-arduino-lcd-clock-using-a-chronodot-rtc/
The key hint here is BCD - Binary-coded decimal - in the function name. In BCD each decimal digit is represented by four bits (half of a byte). As a result the maximum (decimal) number you can store using BCD notation is 99 - 9 in the upper nibble (half of the byte) and 9 in the lower nibble.
Let's take a look at number 12 as an example. Number 12 looks as follows in the binary notation:
12 = %00001010
However in BCD it looks as follows:
12 = %00010010
because
0001 0010
1 2
Now if you look at the decToBcd function val%10 is responsible for calculating the value of the ones place (i.e. the last digit). Since this goes to the lower part of the byte we don't need to do anything special here. val/10*16 first calculates the value of the tens place - val/10. However since the value has to go to the upper half of the byte it needs to be shifted up by four bits - hence *16. Another (in my opinion more readable) way of writing this function would be:
((val / 10) << 4) | (val % 10)
The bcdToDec does the reverse conversion.
RTC usually stores Year in 1 byte as 2 digits only, i.e: 2014 is 14.
And some of them stores it as a number from the year 1970 so 2014 = 44.
So maximum it can hold is 99 in both cases.

How to calculate the parity bit of the following bit sequence?

The sequence is:
00111011
How do i calculate the parity bit for the above sequence? This question is from Databases- The complete book by jeffery ullman (Exercise 13.4.1 a)
I am not sure what the answer to this question should be.
Is it as simple as :
i)Even Parity : the number of 1s is 5 (odd) so just append a 1 and the answer is : 001110111
ii)Odd Parity: likewise , just append 0: 001110110
OR:
am i on a totally wrong path here? I looked up on the net but could not find anything concrete . Also, the text for the above question in the text book is not clear.
Yes, your answers are correct. For the given sequence,
00111011
Odd Parity is 001110110, the parity bit is zero so that the total number of 1's in the code is 5, which is an Odd number.
The Even Parity is 001110111, the parity bit is one so that the total number of 1's in the code is 6, which is an Even number.
You can also use XOR i.e;
00111011
0XOR0=0
0XOR0=0
0XOR1=1
1XOR1=0
0XOR1=1
1XOR0=1
1XOR1=0
0XOR1=1
, The last bit is the parity bit; 1 for even parity, 0 for odd parity. you should make this bit the LSB of the original number (00111011) thereby becoming (001110111).
unsigned char CalEvenParity(unsigned char data)
{
unsigned char parity=0;
while(data){
parity^=(data &1);
data>>=1;
}
return (parity);
}
Alternate implementation of parity:
This involves doing an XOR between the consecutive bits in a particular number in an integer.
The x>>1 left shifts the value by 1 bit and the & 1, gets us the value of the last bit of the number.
Parity of the entire sequence can be visualized as below:- i.e due to the properties of XOR.
1 ^ 0 ^ 1 is same as (1 ^ 0 ) ^ 1 and we extend the same.
def parity_val(x):
parity=0
while x>>1:
parity = (x & 1)^ ((x >>1) & 1)
x = x>> 1
return parity

My bit logic is too outdated. Refresher needed

It's been a while since my assembly class in college (20 years to be exact).
When someone gives you a number, say 19444, and says that X is bits 15 through 8 and Y are bits 7 through 0... how do I calculate values of X and Y?
I promise this is not homework, just a software guy unwisely trying to do some firmware programming.
First of all convert the input number to hexadecimal:
19444 => 0x4BF4
Hex is convenient because every 4 binary bits are one hex digit. Hence, every 2 hex digits are 8 bits, or a byte. Now assuming traditional little-endian notation (look it up!), bits 7 downto 0 are the low byte, bits 15 downto 8 are the high byte:
[7:0] => 0xF4
[15:8] => 0x4B
Using your preferred language, you can get the least significant byte by using a bitwise AND:
Y = 19444 & 0xff
or, the more mathematical:
Y = 19444 % 256
Now, for the most significant byte you can use bit shifts (if the number is larget than two byte, apply the first stage again):
X = 19444 >> 8
(The following assumes C notation). In general, to access the value in bits N through M, where N is the smaller value and the bits are numbered from 0, use:
(value >> N) & (1U << (M - N + 1)) - 1;
So for bits 0..7, use:
(value >> 0) & (1U << 8) - 1
and for bits 8..15, use:
(value >> 8) & (1U << 8) - 1
Note that for the case where "N through M" is the entire width of the type, you can't use the shift as written.
Also, mind the byte order (wheter the most significant byte comes first).
When given bit positions (like "15 through 8"), by convention bit 0 is the least significant bit of the binary number. If you're dealing with a 16-bit number, then bit 15 is the most significant bit.
One hexadecimal digit corresponds to 4 binary digits. So hex FF is 11111111 in binary. Bitwise AND is often used to "mask out" a certain collection of bits.
Nearly all processors provide some form of bitwise shifting. For example, shifting 1010001 right by 4 bits gives you 101.
Combining all this, in C you would typically do something like this:
unsigned short int num;
unsigned char x, y;
num = 19444;
y = num & 0xff; //use bitwise AND to get 8 least-sig bits
x = num >> 8; //right-shift by 8 bits to get 8 most-sig bits

Division, Remainders and only Real Numbers Allowed

Trying to figure out this pseudo code. The following is assumed....
I can only use unsigned and signed integers (or long).
Division returns a real number with no remainder.
MOD returns a real number.
Fractions and decimals are not handled.
INT I = 41828;
INT C = 15;
INT D = 0;
D = (I / 65535) * C;
How would you handle a fraction (or decimal value) in this situation? Is there a way to use negative value to represent the remainder?
In this example I/65535 should be 0.638, however, with the limitations, I get 0 with a MOD of 638. How can I then multiply by C to get the correct answer?
Hope that makes sense.
MOD here would actually return 23707, not 638. (I hope I'm right on that :) )
If you were to switch your order of operations on that last line, you would get the integer answer you're looking for (9, if my calculations are correct)
D = (I * C) / 65535
/* D == 9 */
Is that the answer you're looking for?
Well, one way to handle decimals is this replacement division function. There are numerous obvious downsides to this technique.
ALT DIV (dividend, divisor) returns (decimal, point)
for point = 0 to 99
if dividend mod divisor = 0 return dividend / divisor, point
dividend = divident * 10
return dividend / divisor, 100
Assuming these are the values you're always using for this computation, then I would do something like:
D = I / (65535 / C);
or
D = I / 4369;
Since C is a factor of 65535. This will help to reduce the possibility of overruning the available range of integers (i.e. if you've only got 16 bit unsigned ints).
In the more general case you, if you think there's a risk that the multiplication of I and C will result in a value outside the allowed range of the integer type you're using (even if the final result will be inside that range) you can factor out the GCD of the numerator and denominator as in:
INT I = 41828;
INT C = 15;
INT DEN = 65535;
INT GCDI = GCD(I, DEN);
DEN = DEN / GCDI;
I = I / GCDI;
INT GCDC = GCD(C, DEN);
DEN = DEN / GCDC;
C = C / GCDC;
INT D = (I * C) / DEN;
Where DEN is your denominator (65535 in this case). This will not provide you with the correct answer in all cases, especially if I and C are both mutually prime to DEN and I*C > MAX_INT.
As to the larger question you raise, division of integer values will always loose the decimal component (equivalent to the floor function). The only way to preserve the information contained in what we think of as the "decimal" part is through the remainder which can be derived from the modulus. I highly encourage you to not mix the meanings of these different number systems. Integers are just that integers. If you need them to be floating point numbers, you should really be using floats, not ints. If all you're interested in doing is displaying the decimal part to the user (i.e. you're not really using it for further computation) then you could write a routine to convert the remainder into a character string representing the remainder.

Resources