day before i asked a question regarding the addition of two binary numbers. my problem was solved. the value is C is fine but now i am facing trouble in wrap-around. To handle a wrap-around value I have created another array S and copy value of C (obtained by binary addition of A and B) in S. The addition is performed until carry becomes zero. the value is copied fine but after changing S garbage value is saved in S. I don't know whats wrong. can anyone help please. thanks in advance. Here's the code
char C[9]={'\0','\0','\0','\0','\0','\0','\0','\0','\0'};
char B[9]={'1','1','0','0','0','1','1','1','\0'};
char A[9]={'1','1','0','0','0','0','1','1','\0'};
char carry='0';
char sum[9]={'\0','\0','\0','\0','\0','\0','\0','\0','\0'};
for(int i = 7; i >= 0; i--) {
C[i] = ((A[i] ^ B[i]) ^ carry);
carry = ((A[i] & B[i]) | (A[i] & carry)) | (B[i] & carry);
}
strcpy(sum,C);
for(int l = 7; carry!='0'; l--) {
sum[l] = (C[l]) ^ (carry);
carry = C[l] & carry;
}
cout << endl << sum << endl;
I think you should simply use integers instead of char. Something like the following.
#include <iostream>
using namespace std;
int main() {
int B[8]={1,1,0,0,0,1,1,1};
int A[8]={1,1,0,0,0,0,1,1};
int carry=0;
int sum[8]={0,0,0,0,0,0,0,0};
for(int i = 7; i >= 0; i--) {
sum[i] = ((A[i] ^ B[i]) ^ carry);
carry = ((A[i] & B[i]) | (A[i] & carry)) | (B[i] & carry);
}
if ( carry ) {
int carryArray[8] = {0,0,0,0,0,0,0,1};
carry = 0;
for(int i = 7; i >= 0; i--) {
sum[i] = ((A[i] ^ carryArray[i]) ^ carry);
carry = ((A[i] & carryArray[i]) | (A[i] & carry)) | (carryArray[i] & carry);
}
}
for(int l = 0; l < 8; l++) {
cout << sum[l];
}
cout << endl;
return 0;
}
Better way is to use bitwise operators only (you may consider right and left shifts) and operate over integers.
Problem is that you are operating over ASCII value of 0 and 1, not on 0 and 1. So subtract/add '0' wisely.
char carry='0';
char sum[9]={'\0','\0','\0','\0','\0','\0','\0','\0','\0'};
for(int i = 7; i >= 0; i--) {
C[i] = ((((A[i] - '0') ^ (B[i] - '0')) ^ (carry- '0'))) + '0';
carry = ((((A[i] - '0') & (B[i] - '0')) | ((A[i] - '0') & (carry - '0'))) | ((B[i] - '0') & (carry - '0'))) + '0';
}
strcpy(sum, C);
for(int l = 7; carry != '0'; l--) {
sum[l] = ((C[l] - '0') ^ (carry - '0')) + '0';
carry = ((C[l] - '0') & (carry - '0'))+ '0'; //be careful about operator precedence.
}
Related
I'm new to c++. My teacher left us to do some "tricky" exercises. On this we have to make the sum of two numbers, the trick here is that the maximum value of each int has to be 2 147 483 650 max, so the result would have to be a long long type (I think)
I'm trying to experiment with this and came out with this result:
#include<iostream>
using namespace std;
int main(){
long num_1 = 0;
long num_2 = 0;
cin>>num_1>>num_2;
long long suma = num_1 + num_2;
cout<<"El resultado es "<<suma;
}
The platform says its incorrect, after testing it I realized that when I input 2147483650 + 2147483650 I don't get any result. Why? Am I understanding something wrong?
There are two issues you are running into. This applies to a 32-bit architecture where the range of long is:
-2147483647 to 2147483647
Your input attempt with cin>>num_1>>num_2; fails for values larger than 2147483647 or smaller than -2147483647 -- but you do not catch that because you fail to check the stream state after the attempted input. You would catch the invalid input with:
if (!(std::cin >> num_1 >> num_2)) { /* validate EVERY input */
std::cerr << "error: invalid long input.\n";
return 1;
}
If your the sum of num_1 and num_2 exceeds the range of values that can be stored in a long (4-bytes on most 32-bit architectures) Undefined Behavior results and your program could appear to work normally, crash or anything in between. To ensure there is no overflow in the sum, you must check the result against the limits of the values that can be stored in long.
A simple method is:
/* check for overflow in sum of signed long */
bool safe_sum_long (long& sum, long a, long b)
{
sum = 0;
if (((b > 0) && (a > (std::numeric_limits<long>::max() - b))) ||
((b < 0) && (a < (std::numeric_limits<long>::min() - b)))) {
return false;
}
sum = a + b;
return true;
}
(See: std::numeric_limits for details on use for obtaining limits for all common types)
The function will return false if the value cannot be added safely, or return true filling the reference sum if the value can be added safely.
Putting it altogether, you could do:
#include <iostream>
#include <limits>
/* check for overflow in sum of signed long */
bool safe_sum_long (long& sum, long a, long b)
{
sum = 0;
if (((b > 0) && (a > (std::numeric_limits<long>::max() - b))) ||
((b < 0) && (a < (std::numeric_limits<long>::min() - b)))) {
return false;
}
sum = a + b;
return true;
}
int main (void) {
long num_1 = 0, num_2 = 0, suma = 0;
if (!(std::cin >> num_1 >> num_2)) { /* validate EVERY input */
std::cerr << "error: invalid long input.\n";
return 1;
}
if (safe_sum_long (suma, num_1, num_2)) /* valid sum */
std::cout << "El resultado es " << suma << '\n';
else
std::cerr << "error: overflow occurs in sum.\n";
}
(note: you will want to review Why is “using namespace std;” considered bad practice?)
Example Use/Output
Valid input:
$ ./bin/overflow_long
2147483646
1
El resultado es 2147483647
Valid input but overflow in result:
$ ./bin/overflow_long
2147483647
1
error: overflow occurs in sum.
Invalid input:
$ ./bin/overflow_long
2147483648
error: invalid long input.
While you do not tell us what architecture you are running on, I'm 99% sure you are running in to the limits of long on your system. If you need to work with the the larger number, use a larger type for num_1 and num_2. Either way, you should still check whether the sum can be done without error. Let me know if you have further questions.
You need to change num_1 and num_2 to be long long as well like this:
int main(){
long long num_1 = 0;
long long num_2 = 0;
cin>>num_1;
cin>>num_2;
long long suma = num_1 + num_2;
cout<<"El resultado es "<<suma;
}
#include <cmath>
#include <iostream>
using namespace std;
int main() {
string s1, s2;
int d = 0;
cin >> s1 >> s2;
if (s1.size() == s2.size()) {
int arr[s1.size() + 1];
for (int i = s1.size() - 1; i >= 0; i--) {
if ((s1[i] - '0' + (s2[i] - '0')) % 10 + d > 9) {
arr[i + 1] = ((s1[i] - '0' + (s2[i] - '0')) % 10 + d) % 10;
d = 1;
} else {
arr[i + 1] = (s1[i] - '0' + (s2[i] - '0')) % 10 + d;
d = (s1[i] - '0' + (s2[i] - '0')) / 10;
}
}
arr[0] = d;
if (arr[0] == 0) {
for (int i = 1; i < s1.size() + 1; i++)
cout << arr[i];
} else {
for (int i = 0; i < s1.size() + 1; i++)
cout << arr[i];
}
} else if (s1.size() > s2.size()) {
int arr[s1.size()];
for (int i = s2.size() - 1; i >= 0; i--) {
if ((s1[s1.size() - s2.size() + i] - '0' + (s2[i] - '0')) % 10 + d > 9) {
arr[i + s1.size() - s2.size()] =
((s1[s1.size() - s2.size() + i] - '0' + (s2[i] - '0')) % 10 + d) %
10;
d = 1;
} else {
arr[i + s1.size() - s2.size()] =
(s1[s1.size() - s2.size() + i] - '0' + (s2[i] - '0')) % 10 + d;
d = (s1[s1.size() - s2.size() + i] - '0' + (s2[i] - '0')) / 10;
}
}
if (d == 1) {
for (int i = s1.size() - s2.size() - 1; i >= 0; i--) {
if ((s1[i] - '0') % 10 + d > 9) {
arr[i] = ((s1[i] - '0') % 10 + d) % 10;
d = 1;
} else {
arr[i] = (s1[i] - '0') % 10 + d;
d = (s1[i] - '0') / 10;
}
}
if (d == 1) {
cout << 1;
for (int i = 0; i < s1.size(); i++)
cout << arr[i];
} else {
for (int i = 0; i < s1.size(); i++)
cout << arr[i];
}
} else {
for (int i = 0; i < s1.size() - s2.size() ; i++) cout << s1[i];
for (int i = s1.size() - s2.size(); i < s1.size(); i++) cout << arr[i];
}
} else if (s1.size() < s2.size()) {
int arr[s2.size()];
for (int i = s1.size() - 1; i >= 0; i--) {
if ((s2[s2.size() - s1.size() + i] - '0' + (s1[i] - '0')) % 10 + d > 9) {
arr[i + s2.size() - s1.size()] =
((s2[s2.size() - s1.size() + i] - '0' + (s1[i] - '0')) % 10 + d) %
10;
d = 1;
} else {
arr[i + s2.size() - s1.size()] =
(s2[s2.size() - s1.size() + i] - '0' + (s1[i] - '0')) % 10 + d;
d = (s2[s2.size() - s1.size() + i] - '0' + (s1[i] - '0')) / 10;
}
}
if (d == 1) {
for (int i = s2.size() - s1.size() - 1; i >= 0; i--) {
if ((s2[i] - '0') % 10 + d > 9) {
arr[i] = ((s2[i] - '0') % 10 + d) % 10;
d = 1;
} else {
arr[i] = (s2[i] - '0') % 10 + d;
d = (s2[i] - '0') / 10;
}
}
if (d == 1) {
cout << 1;
for (int i = 0; i < s2.size(); i++)
cout << arr[i];
} else {
for (int i = 0; i < s2.size(); i++)
cout << arr[i];
}
} else {
for (int i = 0; i < s2.size() - s1.size() ; i++) cout << s2[i];
for (int i = s2.size() - s1.size(); i < s2.size(); i++) cout << arr[i];
}
}
return 0;
}
I've been struggling to understand how the function long long number here works. The bit that I can't fully grasp is the for cycles in the if's. Why when we have a number in dec do we have to raise it to that power? Shouldn't we just sum it up and leave it? Also why do we raise the other numbers to that power?
Here is the code:
int counter(long long n, int k) {
int counter = 0;
while (n != 0) {
counter++;
n /= k;
}
return counter;
}
int number2(long long n, int number) {
return (n / (long long) pow(10, number)) % 10;
}
int toDecimal(long long n, int k) {
long long decimal = 0;
for (int i = 0; i < counter(n, 10); i++) {
decimal += number2(n, i)*(int)pow(k, i);
}
return decimal;
}
long long number(char *arr, int start) {
int end = start;
long long number2 = 0;
while (*(arr + end) != ' ' && *(arr + end) != '\0') {
end++;
}
int numberSize = end - start;
if (*(arr + start) != '0') {
for (int i = 0; i < numberSize; i++) {
number2 += (*(arr + start + i) - '0')*pow(10, numberSize - i - 1);
}
return number2;
}
if (*(arr + start) == '0' && (*(arr + start + 1) != 'b' && *(arr + start + 1) != 'x')) {
for (int i = 1; i < numberSize; i++) {
number2 += (*(arr + start + i) - '0')*pow(10, numberSize - i - 1);
}
return toDecimal(number2, 8);
}
if (*(arr + start) == '0' && *(arr + start + 1) == 'b') {
for (int i = 2; i < numberSize; i++) {
number2 += (*(arr + start + i) - '0')*pow(10, numberSize - i - 1);
}
return toDecimal(number2, 2);
}
if (*(arr + start) == '0' && *(arr + start + 1) == 'x') {
int *hex = new int[numberSize - 2];
for (int i = 2; i < numberSize; i++) {
if (*(arr + start + i) >= '0'&&
*(arr + start + i) <= '9')
arr[i - 2] = (*(arr + start + i) - '0');
if (*(arr + start + i) >= 'A'&&
*(arr + start + i) <= 'F')
arr[i - 2] = (int)(*(arr + start + i) - '7');
number2 += arr[i - 2] * pow(16, numberSize - i - 1);
}
delete[] hex;
return number2;
}
}
int main() {
char first[1000];
cin.getline(first, 1000);
int size = strlen(first);
long numberr = number(&first[0], 0);
for (int counter = 0; counter < size; counter++) {
if (first[counter] == ' '&&first[counter + 1] == '+') {
numberr += number(&first[0], counter + 3);
}
}
cout << numberr << "\n";
return 0;
}
The number is a string and is a sequence of single characters representing digits. You have to convert the characters to numbers ("1" --> 1) and then multiply it by the right number of tens to move it to the right place. For example: "123" --> (1 * 10^2) + (2 * 10^1) + (3 * 10^0)
I have an array with x numbers: sets[ ](long numbers) and a char array operations[ ] with x-1 numbers. For each number from sets[ ], its binary form(in 64bits) would be the same as a set of numbers( these numbers being from 0 to 63 ), 1's and 0's representing whether it is inside a subset or not ( 1 2 4 would be 1 1 0 1, since 3 is missing)
ex: decimal 5 --->000...00101 , meaning that this subset will only have those 2 last numbers inside it(#63 and #61)
now,using the chars i get in operations[], i should work with them and the binaries of these numbers as if they were operations on subsets(i hope subset is the right word), these operations being :
U = reunion ---> 101 U 010 = 111
A = intersection ---> 101 A 001 = 001
\ = A - B ---> 1110 - 0011 = 1100
/ = B-A ---> like the previous one
so basically I'd have to read numbers, make them binary, use them as if they were sets and use operations accordingly, then return the result of all these operations on them.
my code :
include <iostream>
using namespace std;
void makeBinaryVector(int vec[64], long xx)
{
// put xx in binary form in array "vec[]"
int k = 63;
long x = xx;
if(xx == 0)
for(int i=0;i<64;i++)
vec[i] = 0;
while(x != 0)
{
vec[k] = x % 2;
x = x / 2;
k--;
}
}
void OperationInA(int A[64], char op, int B[64])
{
int i;
if(op == 'U') //reunion
for(i=0;i<64;i++)
if(B[i] == 1)
A[i] = 1;
if(op == 'A') //intersection
for(i=0;i<64;i++)
{
if((B[i] == 1) && (A[i] == 1))
A[i] = 1;
else
A[i] = 0;
}
if(op == '\\') //A-B
for(i=0;i<64;i++)
{
if( (A[i] == 0 && B[i] == 0) || (A[i] == 0 && B[i] == 1) )
A[i] = 0;
else
if((A[i] == 1) && (B[i] == 1))
A[i] = 0;
else
if((A[i] == 1) && (B[i] == 0))
A[i] = 1;
}
if(op == '/') //B-A
for(i=0;i<64;i++)
{
if(B[i] == 0)
A[i] = 0;
else
if((B[i] == 1) && (A[i] == 0))
A[i] = 1;
else
if((B[i] == 1) && (A[i] == 1))
A[i] = 0;
}
}
unsigned long setOperations(long sets[], char operations[], unsigned int x)
{
unsigned int i = 1; //not 0, since i'll be reading the 1st number separately
unsigned int j = 0;
unsigned int n = x;
int t;
long a = sets[0];
int A[64];
for(t=0;t<64;t++)
A[t] = 0;
makeBinaryVector(A, a); //hold in A the first number, binary, and the results of operations
long b;
int B[64];
for(t=0;t<64;t++) //Hold the next number in B[], in binary form
B[t] = 0;
char op;
while(i < x && j < (x-1) )
{
b = sets[i];
makeBinaryVector(B, b);
op = operations[j];
OperationInA(A, op, B);
i++; j++;
}
//make array A a decimal number
unsigned int base = 1;
long nr = 0;
for(t=63; t>=0; t--)
{
nr = nr + A[t] * base;
base = base * 2;
}
return nr;
}
long sets[100];
char operations[100];
long n,i;
int main()
{
cin>>n;
for(i=0;i<n;i++)
cin>>sets[i];
for(i=0;i<n-1;i++)
cin>>operations[i];
cout<<setOperations(sets,operations,n);
return 0;
}
So everything seems fine, except when im trying this :
sets = {5, 2, 1}
operations = {'U' , '\'}
5 U 2 is 7(111), and 7 \ 1 is 6 (111 - 001 = 110 --> 6)
the result should be 6, however when i Input them like that the result is 4 (??)
however, if i simply input {7,1} and { \ } the result is 6,as it should be. but if i input them like i first mentioned {5,2,1} and {U,} then its gonna output 4.
I can't seem to understand or see what im doing wrong...
You don't have to "convert to binary numbers".
There's no such thing as 'binary numbers'. You can just perform the operations on the variables.
For the reunion, you can use the bitwise OR operator '|', and for the intersection, you can use the bitwise AND operator '&'.
Something like this:
if (op == 'A')
result = a & b;
else if (op == 'U')
result = a | b;
else if (op == '\\')
result = a - b;
else if (op == '/')
result = b - a;
Use bitwise operators on integers as shown in #Hugal31's answer.
Note that integer size is usually 32bit, not 64bit. On a 64bit system you need long long for 64bit integer. Use sizeof operator to check. int is 4 bytes (32bit) and long long is 8 bytes (64bit).
For the purpose of homework etc., your conversion to vector cannot be right. You should test it to see if it outputs the correct result. Otherwise use this:
void makebinary(int vec[32], int x)
{
int bitmask = 1;
for (int i = 31; i >= 0; i--)
{
vec[i] = (x & bitmask) ? 1 : 0;
bitmask <<= 1;
}
}
Note the use of shift operators. To AND the numbers you can do something like the following:
int vx[32];
int vy[32];
makebinary(vx, x);
makebinary(vy, y);
int result = 0;
int j = 1;
for (int i = 31; i >= 0; i--)
{
int n = (vx[i] & vy[i]) ? 1 : 0;
result += n * j;
j <<= 1;
}
This is of course pointless because you can just say int result = X & Y;
so the idea of my class is to take a string of numbers const char* s = "123456654987" i took each couple of number and stored them in one byte
num[0] = 12 , num[1] = 34 and so on .....
this is how i did it
unsigned char* num;
num = new unsigned char[ strlen(s)/2 + strlen(s)%2];
if(strlen(s)%2 == 1)
num[0] = s[0]-'0';
unsigned int i;
int j=strlen(s)%2;
for(i=strlen(s)%2;i<strlen(s);i+=2)
{
int left = s[i] - '0';
int right = s[i+1] - '0';
num[j] = left << 4 ;
num[j] |= right;
j++;
}
for example s[0] = 12 is represented in memory as 00010010 not as 00000110
but now that i'm trying to overload the += operator i didn't know how to proceed
my best try was this but even i know that is not going to work
int i,sum,carry=0;
for(i=this->size-1;i>=0;i--)
{
sum = ((num[i] ^ rhs.num[i]) ^ carry);
carry = ((num[i] & rhs.num[i]) | (num[i] & carry)) | (rhs.num[i] & carry);
num[i] = sum;
}
anyhelp guys
You will need to do the addition one digit (4 bit) at a time because 9+9=18 and 18 won't fit in 4 bits.
x-oring multibit digits however is not the correct operation.. the correct algorithm for sum is something like
int carry = 0;
for(int i=0; i<n; i++) {
if ((i & 1) == 0) {
int x = (a[i] & 15) + (b[i] & 15) + carry;
result[i] = (x & 15);
carry = x > 15;
} else {
int x = (a[i] >> 4) + (b[i] >> 4) + carry;
result[i] |= (x << 4);
carry = x > 15;
}
}
Working in assembler many processors supports detection of an overflow in the lower 4 bits when doing an operation and there are specific instructions to "fix" the result so that it becomes the correct two-digit binary decimal representation (e.g. x86 provides DAA instruction to fix the result of an addition).
Working at the C level however this machinery is not available.
I'm currently trying to solve this programing programing puzzle. The puzzle is about encrypting messages using the following C++ code:
int main()
{
int size;
cin >> size;
unsigned int* a = new unsigned int[size / 16]; // <- input tab to encrypt
unsigned int* b = new unsigned int[size / 16]; // <- output tab
for (int i = 0; i < size / 16; i++) { // Read size / 16 integers to a
cin >> hex >> a[i];
}
for (int i = 0; i < size / 16; i++) { // Write size / 16 zeros to b
b[i] = 0;
}
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++) {
b[(i + j) / 32] ^= ( (a[i / 32] >> (i % 32)) &
(a[j / 32 + size / 32] >> (j % 32)) & 1 ) << ((i + j) % 32); // Magic centaurian operation
}
for(int i = 0; i < size / 16; i++) {
if (i > 0) {
cout << ' ';
}
cout << setfill('0') << setw(8) << hex << b[i]; // print result
}
cout << endl;
/*
Good luck humans
*/
return 0;
}
The objective is to reverse this encoding (that should be a known mathematical operation when identified). The problem i'm facing is that i cannot understand what the encoding works and what all these binary operations are doing. Can you explain me how this encoding works?
Thank you!
To learn what the operations are, break it down loop-by-loop and line-by-line, then apply the rules of precedence. Nothing more, nothing less. If I haven't lost track somewhere in the bitwise swamp, the effect of which all boils down to exclusive XOR'ing the orignal value at index b[(i + j) / 32] by a power of 2 in the range of a signed integer (or 0). The analysis would look something like this:
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++) {
b[(i + j) / 32] ^=
( (a[i / 32] >> (i % 32)) &
(a[j / 32 + size / 32] >>
(j % 32)) & 1 ) <<
((i + j) % 32); // Magic centaurian operation
}
}
What is the first operation:
b[(i + j) / 32] ^=
This in an exclusive OR of the value at that index. If you just let idx represent the jumble that computes the index, you can write it as:
b[idx] ^= stuff
which applying the rules of precedence (right-to-left for ^=) is the same as writing:
b[idx] = b[idx] ^ stuff
The order of precedence tells us me need to figure out stuff before we can apply it to the value of b[idx]. Looking at stuff you have:
| A | << | B |
| C | & | D | | |
| | | E | & 1 | | |
+-----------------+---+-----------------------+-----+----+-------------+
( (a[i/32]>>(i%32)) & (a[j/32+size/32]>>(j%32)) & 1 ) << ( (i+j) % 32 );
Breaking in down, you have A << B, which can be further broken down as:
( C & D ) << B
or finally:
(C & E & 1) << B
The rules of precedence relevant to (C & E & 1) << B are all applied left-to-right giving deference to the parenthesis grouping.
So what is B? It is just a number that the grouping (C & E & 1) will be shifted to the left by. In terms of the index values i and j modded with the number of bits in an integer, it will simply shift the bits in grouping (C & E & 1) to the left by 0-31 bits depending on the combined value of i+j.
The grouping (C & E & 1) is an entirely similar analysis. a[i/32]>>(i%32) is nothing more than the value at a[i/32] shifted to the right by (i%32). E is the same with slightly differnt index manipulation: (a[j/32+size/32]>>(j%32)) which is just the value at that index shifted right by (j%32). The result of both of those shifts are then ANDED with 1. What that means is the entire grouping (C & E & 1) will only have a value if both C & E are odd number values.
Why only odd values? From a binary standpoint, odd numbers are the only values that will have the one-bit 1. (e.g. 5 & 7 & 1 (101 & 111 & 1) = 1). If any of the values are even or 0, then the whole grouping will be 0.
Understanding the grouping (C & E & 1) (or what we have largely grouped as A), you can now look at:
A << B
Knowing A will be 0 or 1, you know the only way the result of the shift will have value is if A is 1, and then the result of the group will just be the value of 1 shifted left by B bits. Knowing B has the range of 0-31, then the range of values for A << B are between 0 - 2147483648, but since you are shifting by between 0 - 31, the values for A << B will only be the positive powers of two between 0 - 2147483648 (binary: 0, 1, 10, 100, 1000, etc...)
Then that finally brings us to
b[idx] = b[idx] ^ stuff
which when you exclusively OR anything by a power of two, you only serve to flip the bit at the power of two in that number. (e.g. 110101 (26) ^ 1000 (8) = 111101 (61)). All other bits are unchanged. So the final effect of all the operations is to make:
b[idx] = b[idx] ^ stuff
nothing more than:
b[idx] = b[idx] ^ (power of two)
or
b[idx] = b[idx] ^ 0 /* which is nothing more than b[idx] to begin with */
Let me know if you have any questions. You can easily dump the index calculations to look at the values, but this should cover the operations at issue.
This code snippet is doing a Carry-free Multiplication Operation on the first half parts of the array (a[0:size/32]) and the second half parts of the array (a[size/32:size/16]).
I write an equivalent version in binary below the original version, hope this might help you.
#include <iostream>
#include <iomanip>
#include <ios>
using namespace std;
int main() {
int size;
cin >> size;
unsigned int* a = new unsigned int[size / 16]; // <- input tab to encrypt
unsigned int* b = new unsigned int[size / 16]; // <- output tab
bool *a1 = new bool[size];
bool *a2 = new bool[size];
bool *bb = new bool[size * 2];
for (int i = 0; i < size / 16; i++) { // Read size / 16 integers to a
cin >> hex >> a[i];
}
for (int i = 0; i < size * 2; i++) {
if (i < size) {
a1[i] = (a[i / 32] & (1 << (i % 32))) > 0; // first `size` bits are for a1
} else {
a2[i - size] = (a[i / 32] & (1 << (i % 32))) > 0; // rest `size` bits are for a2
}
}
for (int i = 0; i < size / 16; i++) { // Write size / 16 zeros to b
b[i] = 0;
}
for (int i = 0; i < size * 2; i++) {
bb[i] = 0;
}
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++) {
b[(i + j) / 32] ^= ( (a[i / 32] >> (i % 32)) &
(a[j / 32 + size / 32] >> (j % 32)) & 1 ) << ((i + j) % 32); // Magic centaurian operation
}
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++) {
bb[i + j] ^= (a1[i] & a2[j] & 1); // some operation as multiply (*) do
}
for(int i = 0; i < size / 16; i++) {
if (i > 0) {
cout << ' ';
}
cout << setfill('0') << setw(8) << hex << b[i]; // print result
}
cout << endl;
for(int i = 0; i < size / 32 * 2; i++) {
if (i > 0) {
cout << ' ';
}
unsigned int hex_number = 0;
for (int j = 0; j < 32; j++) hex_number += bb[i * 32 + j] << j;
cout << setfill('0') << setw(8) << hex << hex_number; // print result
}
cout << endl;
return 0;
}