How can I write the Twos complement and return a hex string ?
Show older comments
Ex:
E5
+
83
=
8E
I k
% ~add 1 to bin_int
*****************************************
Thank you.
8 Comments
Irwin2020
on 23 Oct 2018
James Tursa
on 23 Oct 2018
Edited: James Tursa
on 23 Oct 2018
When you say the "strings are any length >= 1" does that mean the strings could be hundreds of digits long? Or is there in fact a practical limit like 8 or 16? Because if it is the latter, then you can simply sign extend and convert to integers and let MATLAB do the calculations for you since MATLAB uses 2's complement for integer storage (on all machines it currently runs on?).
Irwin2020
on 24 Oct 2018
Irwin2020
on 24 Oct 2018
Guillaume
on 24 Oct 2018
It makes no sense to say that hex values are signed if you don't specify the number of bits used (or which bit is the sign bit).
The signed 8-bit value A0 is -96, the signed 16-bit value A0 is 160.
Other than that issue, if you're limiting yourself to a maximum of 16 hex digits (thus 64 bits), then as James said, you can simply convert to integer and let matlab do the addition. Note that for 64 bits integer you cannot use hex2dec for the conversion.
Guillaume
on 25 Oct 2018
And as I said, -142 is not representable as 8-bit integer. So what should the answer be? Matlab answer would be -128, for a C program this would be undefined and could result in anything although some implementations may return +114.
madhan ravi
on 20 Nov 2018
If you close the question that have answers you will unlikely receive any help further plus it ignores the efforts of the answerers
Accepted Answer
More Answers (2)
James Tursa
on 29 Oct 2018
Edited: James Tursa
on 29 Oct 2018
If you really have to write a for-loop for this, a simple algorithm for adding two 2's complement signed integers represented as hex strings is:
1) Convert each hex string to binary strings of the appropriate length (based on location of sign bit)
2) Add up the bits in the usual fashion ignoring overflow (e.g., grade school arithmetic using a carry bit. SEE NOTE!)
3) Look for overflow (both operands are the same sign but result is opposite sign)
4) Convert the result binary string back into hex
NOTE: You don't have to do anything special for step 2 regarding the signs of the operands. You just add up the bits (including the "sign" bit) like normal grade school arithmetic. If the carry bit overflows past the sign bit in this process you simply ignore it. Doing it this way, the bits of the answer will be correct regardless of the signs of the operands ... just make sure you treat the sign bit just like any other bit in this adding process. Then all you need is the simple check for overflow by examining the signs of the operands and the sign of the result. Of course, you may simply choose to ignore any actual overflow and let the result wrap around like many C/C++ compilers do.
12 Comments
Guillaume
on 30 Oct 2018
Step 1 can be achieved with:
reshape(dec2bin(sscanf(yourhexadecimalstring, '%1x'), 4)' - '0', 1, [])
For step 3, it is critical to know which bit is the sign bit. The sign bit cannot move around.
let the result wrap around like many C/C++ compilers do
This is the behaviour defined by the C and C++ standard for unsigned integers, and the compiler must implement it.
For signed integers, the behaviour of overflow is undefined. The compiler is free to do whatever it wants, it doesn't even have to be consistent. It can wrap around like for unsigned, it can issue a compiler error (better) or it can start World War 3.
James Tursa
on 30 Oct 2018
"... For step 3, it is critical to know which bit is the sign bit. The sign bit cannot move around ..."
Good point. The algorithm assumes that both hex strings have the sign bit in the same spot. If not, then you would have to convert the shorter one to the longer one first.
James Tursa
on 30 Oct 2018
"... or it can start World War 3 ..."
Or become self-aware and start building Terminators. Maybe this is how it all started ...
Irwin2020
on 1 Nov 2018
James Tursa
on 1 Nov 2018
Edited: James Tursa
on 1 Nov 2018
You will need to show us your code, not just a description of your code. I don't see how you can do this without implementing a carry bit in some form, regardless of whether you are doing the adding in hex or binary or decimal.
Irwin2020
on 1 Nov 2018
Irwin2020
on 1 Nov 2018
Guillaume
on 1 Nov 2018
I have no idea or why you'd use for loops when they're not needed. Certainly you can add as many unneeded for loops to you code.
The code you show seem to use result1 before it is even created.
I have no idea why you use extractAfter when all you're doing is:
h1 = hex1(end-1:end)
h2 = hex2(end-1:end)
which is a lot clearer and faster.
The code you've written above seems to be a rework of my answer with some addition that don't appear to do much.
Irwin2020
on 1 Nov 2018
James Tursa
on 1 Nov 2018
Edited: James Tursa
on 1 Nov 2018
All of that typecasting stuff is completely unnecessary and complicated. Just using your idea of adding two hex characters at a time, here is the setup:
hex1 = 'AA10EFDE'; % arbitrary hex string
hex2 = '2FDE01CB'; % arbitrary hex string
carry = 0; % initial carry bit
nbits = ___; % bit length of the numbers
Then each iteration would contain this simple code:
h1 = _______; % code here to pick off the appropriate two hex digits
h2 = _______; % code here to pick off the appropriate two hex digits
h = dec2hex(hex2dec(h1) + hex2dec(h2) + carry,3); % force three hex digit result
hsum = h(2:3); % the two hex digit result of this iteration
carry = h(1) - '0'; % the carry bit for the next iteration
There is no need for any int32, uint32, or typecasting stuff. Just pick off the appropriate hex digits, convert them to decimal (as unsigned) and add them up, and get your resulting hex digits with the carry bit. You simply need to wrap this iteration code in a loop and put in the logic for when the loop is done and overflow checking (based on the value of nbits). The hsum results get built up into the final answer.
The logic for picking off the appropriate hex digits and concatenating the hsum iteration results could be done in several ways. E.g., shrinking the hex1 and hex2 strings by two hex digits each time, or by appropriate indexing into them, etc. I leave that to you.
The sign bit and overflow stuff will require some special code for that last iteration if the sign bit is in the "middle" instead of at the left boundary of the first hex digit. But it can be done. (That is the primary reason why the binary representation is easier to work with for this and why I suggested it).
James Tursa
on 2 Nov 2018
Putting that in a loop will be the easy part. It is the sign bit and overflow stuff that will be the hard part. Do you have any constraints on where the sign bit might be? Will it always be at the left edge of a 2-byte boundary? Or could it be anywhere? Writing generic code for a sign bit that could be anywhere could easily take up the bulk of your code and will be more complicated than what I have already written above, whereas if you restrict the cases to 2-byte boundaries that simplifies things greatly.
Guillaume
on 2 Nov 2018
all I need is that if you are able to show me a for loop (i) to add the hex values
I have done just that in the answer that at the moment is below this one.
With regards to sign bits. We still haven't had any explanation of how that work with variable length hex strings. Having a sign bit that moves around would be completely nonsensical. Would FF be the signed 8-bit decimal value -1 or the signed 16-bit decimal value 255? The only thing that would work would be if the sign bit was the LSB.
Guillaume
on 1 Nov 2018
Function to add hexadecimal strings of arbitrary length:
function hexsum = addhex(hex1, hex2)
assert(all(ismember(hex1, '0123456789ABCDEF')), 'hex1 is not a hexadecimal string');
assert(all(ismember(hex2, '0123456789ABCDEF')), 'hex2 is not a hexadecimal string');
%pad both strings to the same length and to a length multiple of 2 for easy byte conversion
maxlength = 2*ceil(max(numel(hex1), numel(hex2))/2);
hex1 = [repelem('0', maxlength - numel(hex1)), hex1];
hex2 = [repelem('0', maxlength - numel(hex2)), hex2];
%split into bytes, convert to decimal
dec1 = hex2dec(reshape(hex1, 2, [])');
dec2 = hex2dec(reshape(hex2, 2, [])');
%sum with carry
decsum = zeros(size(dec1));
carry = 0;
for row = numel(dec1):-1:1
decsum(row) = dec1(row) + dec2(row) + carry;
carry = decsum(row) > 255;
end
decsum = mod(decsum, 256);
%convert back to hex, remove leading 0
hexsum = reshape(dec2hex(decsum, 2)', 1, []);
hexsum = hexsum(~cumprod(hexsum == '0'));
end
The numbers are assumed unsigned as otherwise you would have to specify the sign bit. A loop is only needed for the addition with carry. For everything, it's simpler to do it without a loop.
1 Comment
Irwin2020
on 24 Nov 2018
Categories
Find more on Data Type Conversion in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!