Converting characters to decimal while I need to append the values together - append

I'm receiving two characters from a serial port let's say '\x10' and 'Q'.
I need to convert them to decimal.
Each character indicates a two byte Hex code "10" and "51"
However, I need to append them and have "1051" and then convert this to decimal to give me 4177 which indicates my voltage value multiplied by 100.
So what is the question?
I know printf("%x", ...) gives me a HEX value however it does not give me this ability to modify and append two hex code to get one. ( It just shows the HEX format)
Then what is the actual way to convert and append them together?

This was pretty easy but tricky. And I got confused by division in the received packet! It was just a simple hex to dec and dec to hex in order to append to chunk together!
int x, y, z, v, n;
string s = SerialBuffer ;
char ch;
ch = SerialBuffer[17];
char ch2;
ch2 = SerialBuffer[16];// s.at(16);
x = (ch / 16);// +(int)sum;
y = (ch % 16);
z = (ch2 / 16);
v = ch2 % 16;
n = v + z * 16 + y * 256 + x * 4096; // decimal

Related

How to Increment a 3 digit Number(User Input) by 1 in Brainfuck?

How to Increment a 3 digit Number by 1 in Brainfuck?
For Example. Getting a User input of 699 this code should output 700.
This is something i Tried but its not working .
,>,>,+
<<.>.>.
The reason it doesn't work is because you don't have a 3 digit number in memory. You have three ASCII values from 48-57 (characters 0-9). I will explain how to do what you need to, but won't provider the actual BF code for multiplication etc, you can find those elsewhere.
Let's call the characters X, Y and Z
First of all we need to convert them to a number between 0 and 9. Assuming that the user enters digits only, we can do this by subtracting 48 (ASCII character 0) from the ASCII value.
Ok so now we have three numbers from 0-9 as follows:
A = X - 48
B = Y - 48
C = Z - 48
Problem is they're still three separate digits and not one number. What's the actual number? In this case the number can be built in the following way:
N = 100A + 10B + C
So, you need to multiply A by 100, B by 10, C by 1, and then adding them all together. Could be done as follows:
N = A
N = (N * 10) + B
N = (N * 10) + C
After you've done that, you have an actual number in one cell, and you can increment it by doing N = N + 1 which in BF is a single +
Now this would work for numbers up to 255, which is the largest number that a BF cell can hold. You want to work with larger numbers? It gets more complicated, because now you have to split that number up into two or more cells, propagating the carries yourself etc. I won't go into that here because that gets much more complex (though there are algorithms you can find online to help as well) and I think this is enough to get you started.
EDIT: I realized that your code is also trying to print the incremented value. This requires more work, because the . command outputs the value of that cell as is as an ASCII character. But you need to output three digits. To do that you'd need to reverse the process above to split the number into three digits as follows:
C = N % 10
N = N / 10
B = N % 10
N = N / 10
A = N
Then you need to convert them from a number 0-9 to ASCII characters again as follows:
X = A + 48
Y = B + 48
Z = C + 48
and then finally you can output characters X, Y and Z in that order which would be the human readable incremented number.

Convert 64 bit numbers from binary to decimal using uint64

I want to convert 64 bit numbers from binary to decimal. Since dec2bin only supports up to 52 bits, I thought I could roll my own function and use uint64 to go beyond this limit:
function [dec] = my_bin2dec(bin)
v = uint64(length(bin)-1:-1:0);
base = uint64(2).^v;
dec = uint64(sum(uint64(base.*(uint64(bin-'0')))));
end
However, it does not work as expected:
my_bin2dec('111000000000000000000000000000000000001010110101011101000001110')
ans =
8070450532270651392
my_bin2dec('111000000000000000000000000000000000001010110101011101000001111')
ans =
8070450532270651392
Whereas this is the correct result:
(111000000000000000000000000000000000001010110101011101000001110)bin
= (8070450532270651918)dec
(111000000000000000000000000000000000001010110101011101000001111)bin
= (8070450532270651919)dec
What am I missing? It seems like there is some operation still performed using 52bit double arithmetic, but I don't know which one.
I checked if the operations are available for uint64 and it seems that the ones I use (power, times, sum) are there:
>> methods uint64
Methods for class uint64:
abs bitxor diff isinf mod plus sum
accumarray bsxfun display isnan mpower power times
all ceil eq issorted mrdivide prod transpose
and colon find ldivide mtimes rdivide tril
any conj fix le ne real triu
bitand ctranspose floor linsolve nnz rem uminus
bitcmp cummax full lt nonzeros reshape uplus
bitget cummin ge max not round xor
bitor cumprod gt min nzmax sign
bitset cumsum imag minus or sort
bitshift diag isfinite mldivide permute sortrowsc
You were right in saying that
It seems like there is some operation still performed using 52bit double arithmetic.
The problem is in line
dec = uint64(sum(uint64(base.*(uint64(bin-'0')))));
The operation sum(uint64(base.*(uint64(bin-'0')))) gives a double result, which only has about 15 significant digits. That's why your lowest digits are wrong. Subsequent conversion into uint64 doesn't help, because precision has already been lost.
The solution is to sum natively in uint64. This gives a uint64 result with its full precision:
dec = sum(uint64(base.*(uint64(bin-'0'))), 'native');
Had the same thought as #beaker, break it into chunks:
%% dec2bin
x=intmax('uint64')
MSBs = dec2bin( bitshift(x,-32) ,32)
LSBs = dec2bin( bitand(x, hex2dec('FFFFFFFF')) ,32)
y = [MSBs LSBs]
%% bin2dec
MSBs = y(1:32)
LSBs = y(33:64)
z = bitor( bitshift( uint64(bin2dec(MSBs)) , 32 ) , uint64(bin2dec(LSBs)) )
% (now x = z)
Oddly enough, it seems that dec2bin doesn't give an error, but does give incorrect answers for 64 bit numbers:
dec2bin( intmax('uint64') )
ans =
10000000000000000000000000000000000000000000000000000000000000000

Hashing integer coordinates of different sizes

I'm trying to hash some 3D coordinates to a 16-bit integer.
The coordinates have the following constraints:
x [0, 16]
y [0,256]
z [0, 16]
Is it possible to get O(1) access, zero collisions, and still fit it in a 16-bit word?
My thought was to shift the coordinates such that x takes up the first 4 bits, y the next 8 and z the last 4. After some iterations I came up with the following which shifts and masks the bits such that they shouldn't overlap and cause collisions:
unsigned int hash(unsigned char x, unsigned char y, unsigned char z) {
return (x << 12) & 0xF000 |
(y << 8) & 0x0FF0 |
z & 0x000F;
}
However this does produce collisions somehow! I'm not sure why and would grateful if anyone could tell me.
In researching hashing I've found that z-order curves/morton encoding would be a good way to go but that assumes the range of the coordinates in each dimension is constant. Could an option be to morton encode x and z into 8 bits and somehow combine that with the y coordinate for a 16-bit word?
I tried instead mapping to a 32-bit integer with the following code.
return ((x) << 24) & 0xFF000000 |
((y) << 16) & 0x00FFFF00 |
z & 0x000000FF;
My unit tests passed and it seems to work however I fear that this may eat a lot more memory than a 16-bit hash.
I'll mark this as answered but the original question still stands if anyone can enlighten me.
It might be because you’ve written
x & 0x000F
when it should be
z & 0x000F
The second shift count is also wrong, so try:
unsigned int hash(unsigned char x, unsigned char y, unsigned char z) {
return (x << 12) & 0xF000 |
(y << 4) & 0x0FF0 |
z & 0x000F;
}

Generating Unique ID Number from Two Integers

Given 2 integers a and b (positive or negative). Is there any formula / method for generating unique ID number?
note: 1. result from f(a,b) and f(b,a) should be different. 2. calculating f(a,b) for x times (x > 1), the result should be same.
To make clear about the question, this function f(n) = (n * p) % q (where n=input sequence value, p=step size, q=maximum result size, n=non-negative integer, n < q, p < q, p ⊥ q (coprime)) will give unique ID number.
But, in my requirement, input are two numbers, a and b can be negative or positive integer.
any reference is appreciable
You could generate a long (64 bit) from 2 integers (32 bit) by just right bit shifting the first integer with 32 and then add the second integer.
private long uniqueId(int left, int right) {
long uniqueId = (long) left;
uniqueId = uniqueId <<< 32;
uniqueId += (long) right;
return uniqueId;
}
Say your integers have a range in [MIN_INT,MAX_INT]. Then, given an integer n from this range, the function
f(n) = n - MIN_INT
attributes a unique positive integer f(n) in the range [0, MAX_INT - MIN_INT], which is often called a rank.
Denote M = MAX_INT - MIN_INT + 1. Then, to find a unique id g(n,m) of two concatenated integers n and m, you can use the common access style also used for two-dimensional arrays:
g(n,m) = f(n)*M + f(m)
That is, you simply offset the second integer by the largest possible value and count on.
Practically, of course, you have to be careful in order to avoid overflows -- that is, you should use some suited data types.
Here is an example: say your integers come from the range [-1,4], thus M=6. Then, for two integers n=3 and m=-1 out of this range, g(n,m) = 3*6 + 0 = 18 can be used as id.

how to sum digits in a multi-digit number Matlab

I wonder how to sum digits for a multi-digit number in Matlab.
For example 1241= 1+2+4+1 = 8
String-based answer:
>> n = 1241;
>> sum(int2str(n)-48)
ans =
8
The number is first converted to a string representation using int2str, then the ASCII code for '0' (i.e. 48) is subtracted from the ASCII code for each element of the string, producing a numeric vector. This is then summed to get the result.
A = 35356536576821;
A = abs(A);
xp = ceil(log10(A)):-1:1;
while ~isscalar(xp)
A = sum(fix(mod(A,10.^xp)./10.^[xp(2:end) 0]));
xp = ceil(log10(A)):-1:1;
end
this is the numeric approach
This one is the solution is character approach:
A = '35356536576821';
A = char(regexp(A,'\d+','match'));
while ~isscalar(A)
A = num2str(sum(A - '0'));
end
Both, first take the absolute number (strip the minus) then: the numeric one counts with log10() how many digits a number has and through modulus and divisions extracts the digits which are summed, while the char approach convert to numeric digits with implicit conversion of - '0', sums and converts back to string again.
Another all-arithmetic approach:
n = 1241; %// input
s = 0; %// initiallize output
while n>0 %// while there is some digit left
s = s + mod(n-1,10)+1; %// sum rightmost digit
n = floor(n/10); %// remove that digit
end
Youcan use this code
sum(int2str(n)-48)
where n, is your input number.