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.
Related
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;
I am new to c++. I want to take input a unsigned 128 bit integer using scanf and print it using printf. As I am new to c++ , I only know these two methods for input output. Can someone help me out?
You could use boost, but this library set must be installed yourself:
#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>
int main()
{
using namespace boost::multiprecision;
uint128_t v = 0;
std::cin >> v; // read
std::cout << v << std::endl; // write
return 0;
}
If you want to get along without boost, you can store the value into two uint64_t as such:
std::string input;
std::cin >> input;
uint64_t high = 0, low = 0, tmp;
for(char c : input)
{
high *= 10;
tmp = low * 10;
if(tmp / 10 != low)
{
high += ((low >> 32) * 10 + ((low & 0xf) * 10 >> 32)) >> 32;
}
low = tmp;
tmp = low + c - '0';
high += tmp < low;
low = tmp;
}
Printing then, however, gets more ugly:
std::vector<uint64_t> v;
while(high | low)
{
uint64_t const pow10 = 100000000;
uint64_t const mod = (((uint64_t)1 << 32) % pow10) * (((uint64_t)1 << 32) % pow10) % pow10;
tmp = high % pow10;
uint64_t temp = tmp * mod % pow10 + low % pow10;
v.push_back((tmp * mod + low) % pow10);
low = low / pow10 + tmp * 184467440737 + tmp * /*0*/9551616 / pow10 + (temp >= pow10);
high /= pow10;
}
std::vector<uint64_t>::reverse_iterator i = v.rbegin();
while(i != v.rend() && *i == 0)
{
++i;
}
if(i == v.rend())
{
std::cout << 0;
}
else
{
std::cout << *i << std::setfill('0');
for(++i; i != v.rend(); ++i)
{
std::cout << std::setw(8) << *i;
}
}
Above solution works up to (including)
340282366920938463463374516198409551615
= 0x ffff ffff ffff ffff ffff ad06 1410 beff
Above, there is an error.
Note: pow10 can be varied, then some other constants need to be adjusted, e. g. pow10 = 10:
low = low / pow10 + tmp * 1844674407370955161 + tmp * 6 / pow10 + (temp >= pow10);
and
std::cout << std::setw(1) << *i; // setw also can be dropped in this case
Increasing results in reducing the maximum number for which printing still works correctly, decreasing raises the maximum. With pow10 = 10, maximum is
340282366920938463463374607431768211425
= ffff ffff ffff ffff ffff ffff ffff ffe1
I don't know where the error for the very highest numbers comes from, yet, possibly some unconsidered overflow. Any suggestions appreciated, then I'll improve the algorithm. Until then, I'd reduce pow10 to 10 and introduce a special handling for the highest 30 failing numbers:
std::string const specialValues[0] = { /*...*/ };
if(high == 0xffffffffffffffff && low > 0xffffffffffffffe1)
{
std::cout << specialValues[low - 0xffffffffffffffe2];
}
else
{
/* ... */
}
So at least, we can handle all valid 128-bit values correctly.
You can try from_string_128_bits and to_string_128_bits with 128 bits unsigned integers in C :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
__uint128_t from_string_128_bits(const char *str) {
__uint128_t res = 0;
for (; *str; res = res * 10 + *str++ - '0');
return res;
}
static char *to_string_128_bits(__uint128_t num) {
__uint128_t mask = -1;
size_t a, b, c = 1, d;
char *s = malloc(2);
strcpy(s, "0");
for (mask -= mask / 2; mask; mask >>= 1) {
for (a = (num & mask) != 0, b = c; b;) {
d = ((s[--b] - '0') << 1) + a;
s[b] = "0123456789"[d % 10];
a = d / 10;
}
for (; a; s = realloc(s, ++c + 1), memmove(s + 1, s, c), *s = "0123456789"[a % 10], a /= 10);
}
return s;
}
int main(void) {
__uint128_t n = from_string_128_bits("10000000000000000000000000000000000001");
n *= 7;
char *s = to_string_128_bits(n);
puts(s);
free(s); // string must be freed
// print 70000000000000000000000000000000000007
}
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;
}
I have a vector of integers vector<int> that has 48 items in it. I want to extract binary data out of this(not sure if this is correct way to call it please edit it if it's wrong) i.e. a sequence of one or more bits and then convert them to a primitive type like int. I have come up with this solution:
int extractValue(vector<int> v, int startBit, int endBit) {
int beginByteIndex = (startBit / 8);
int endByteIndex = (endBit / 8);
vector<bool> bits;
bits.clear();
int startIndex = startBit % 8;
int endIndex = endBit % 8;
int value = v[beginByteIndex];
value = (value << startIndex);
int temp = 8;
if (beginByteIndex == endByteIndex) {
temp = endIndex + 1;
}
for (int i = startIndex; i < temp; i++) {
int temp = 0x80 & value;
bits.push_back(temp);
value <<= 1;
}
for (int i = beginByteIndex + 1; i < endByteIndex; i++) {
value = v[i];
for (int j = 0; j < 8; j++) {
int temp = 0x80 & value;
bits.push_back(temp);
value <<= 1;
}
}
if (endByteIndex > beginByteIndex) {
value = v[endByteIndex];
for (int i = 0; i <= endIndex; i++) {
int temp = 0x80 & value;
bits.push_back(temp);
value <<= 1;
}
}
int size = bits.size();
int p = 1;
int result = 0;
for (int i = size - 1; i >= 0; i--) {
result += (bits[i] * p);
p *= 2;
}
return result;
}
but this function is long, difficult to read and is done in C style. could someone please suggest a C++ way of doing this. I'm almost certain that C++ has a good, short and elegant way of doing this. also please edit the question so others with similar problem can benefit from it. Unfortunately My English is not that good to express it in a more general way.
EDIT:
as requested in comments for example I want to extract following information with following positions and length:
int year = extractValue(data, 0, 6);
int month = extractValue(data, 7, 10);
int day = extractValue(data, 11, 15);
a simple solution:
convert each byte to hex string (ostringstream or even sprintf can help), you got 2 digits, range is 0 to F.
for each hex digit you can create the bitmap like this:
0 = 0000,
1 = 0001,
2 = 0010,
...,
F = 1111,
add bits to the vector according to the bitmap
to recover - you take 4 bits and translate it back to digit, then take 2 digits and convert back to byte (say by adding 0x to the hex, isringstream to byte).
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.
}