Here is code which returns number of leading zeros from Hacker's Delight book:
#include <iostream>
using namespace std;
int nlz(unsigned x) {
int n;
if (x == 0) return(32);
n = 1;
if ((x >> 16) == 0) {n = n +16; x = x <<16;}
if ((x >> 24) == 0) {n = n + 8; x = x << 8;}
if ((x >> 28) == 0) {n = n + 4; x = x << 4;}
if ((x >> 30) == 0) {n = n + 2; x = x << 2;}
n = n - (x >> 31);
return n;
}
int main(){
int x;
cin>>x;
cout<<nlz(x)<<endl;
return 0;
}
and when I enter number 8 it return 8 and is it correct maybe it should return 3 yes?
8//1000
It returns the number of leading bits that is zero in an unsigned integer , and it assumes an integer is 32 bits.
8 is 0000 0000 0000 0000 0000 0000 0000 1000 binary, and it should return 28 for that, as there's 28 leading bits zero before the first 1 bit. If you're running this on something where an integer is not 32 bits, it won't work.
This algorithm will return the number of leading zero bits from a 32-bit value. I don't see how it would return 8 for an input of 8.
Related
I'm trying to reverse engineer a game function, which takes an integer and returns a 64-bit integer, by writing a function which returns the original value before it was put through the game function. How do I achieve this?
I have only managed to reverse these steps:
x = ((1 - x) << 16)
I'm not sure how to reverse the addition without the original value.
Here is the game function:
int64_t convert(int x) {
if (x <= 0)
return (1 - ((((x + 1) >> 31) + x + 1) >> 16));
else
return 0;
}
For example, if the original value was -5175633 then the converted value would be 80, I need to get the original value from 80.
I don't think this is possible. When you right-shift an integer, bits are lost. This means there are multiple input values that would return the same output value.
Sorry Victor, but your solution doesn't work. You ought to be comparing r and i, not c and cc.
Let's assume, with the step (1 - ((((x + 1) >> 31) + x + 1) >> 16)), x has converted to y, the we get:
y = 1 - ((((x + 1) >> 31) + x + 1) >> 16)
1 - y = (((x + 1) >> 31) + x + 1) >> 16
(1 - y) << 16 = (x + 1) >> 31 + x + 1
If x <= 0, then x + 1 <= 1. However this can't decide the sign bit. So we should assume once more.
if x + 1 < 0, then (x + 1) >> 31 is -1, which x < -1, y which is 1 - ((((x + 1) >> 31) + x + 1) >> 16), is 1 - (x >> 16)
(1 - y) << 16 = -1 + x + 1
(1 - y) << 16 = x
if x + 1 >= 0, then (x + 1) >> 31 is 0, which x >= -1, and y, which is 1 - ((((x + 1) >> 31) + x + 1) >> 16), is 1. (Note: now x can only be 0 or -1)
(1 - y) << 16 = x + 1
(1 - y) << 16 - 1 = x
So, include these two results together, we can get:
int reverse_convert(int64_t y) {
if (y == 1)
return (1 - y) << 16 - 1; // However, either x = 0 or x = 1 can produce this result.
else
return (1 - y) << 16;
// the condition of y == 0, corresponding to the original "else return 0;", is ignored.
}
Besides, the convert function is a Surjective-only function, which means multiple input can get the same output, then it is impossible to reverse precise output into input.
I will assume sizeof(int) is 4. And all the operations are done on 32 bits.
#include <iostream>
using namespace std;
int64_t convert(int32_t x) {
if (x <= 0)
return (1 - ((((x + 1) >> 31) + x + 1) >> 16));
else
return 0;
}
int32_t revconvert(int64_t r) {
if (r == 0) return 0;
if (r == 1) return -1;
return (1-r) << 16;
}
int main()
{
int32_t i;
for (i=0;i>-10000000;--i) {
auto c = convert(i);
auto r = revconvert(c);
auto cc = convert(r);
if( c!=cc) break;
}
cout << i << endl; // just to see if we got to the end
cout << convert(-5175633) << endl; // Will give 80
cout << revconvert(80) << endl; // Will give -5177344
cout << convert(-5177344) << endl; // Will give 80
return 0;
}
There seems to be some kind of misconception that this is for a contest.
I'm trying to work through an assignment and I've been stuck on this for an hour now.
/*
* isLessOrEqual - if x <= y then return 1, else return 0
* Example: isLessOrEqual(4,5) = 1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 24
* Rating: 3
*/
int isLessOrEqual(int x, int y)
{
int greater = (x + (~y + 1))>>31 & 1;
return !(greater)|(!(x^y));
}
I'm only able to use bitwise operators, as instructed in the comments.
I cannot figure out how to solve x <= y;
My thought process is that I can set x as its two's complement (~x +1) and add it with Y. If it is negative, X is greater than Y. Therefore, by negating that I can get the opposite effect.
Similarly, I know that !(x^y) is equivalent to x==y.
However,
doing !(greater)|(!(x^y)) does not return the proper value.
Where am I messing up? I feel like I'm missing a small bit of logic.
Those functions don't fully work because of the overflow, so that's how I solved the problem. Eh...
int isLessOrEqual(int x, int y) {
int diff_sgn = !(x>>31)^!(y>>31); //is 1 when signs are different
int a = diff_sgn & (x>>31); //diff signs and x is neg, gives 1
int b = !diff_sgn & !((y+(~x+1))>>31); //same signs and difference is pos or = 0, gives 1
int f = a | b;
return f;
}
If x > y, then y - x or (y + (~x + 1)) will be negative, hence the high bit will be 1, otherwise it will be 0. But we want x <= y, which is the negation of this.
/*
* isLessOrEqual - if x <= y then return 1, else return 0
* Example: isLessOrEqual(4,5) = 1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 24
* Rating: 3
*/
int isLessOrEqual(int x, int y)
{
return !(((y + (~x + 1)) >> 31) & 1);
}
Even better, drop the shift operator and use a bit mask on the high bit:
int isLessOrEqual(int x, int y)
{
return !((y + (~x + 1)) & 0x80000000);
}
EDIT:
As a commenter pointer out, the above version is susceptible to arithmetic overflow errors. Here is another version that covers the edge cases.
#include <limits>
int isLessOrEqual(int x, int y)
{
static int const vm = std::numeric_limits<int>::max();
static int const sm = ~vm;
return !! ((x & ~y | ~(x ^ y) & ~((y & vm) + ~(x & vm) + 1)) & sm);
}
Explanation: the overall strategy is to treat the sign bit of the inputs as logically distinct from the rest of the bits, the "value bits," and perform the subtraction as in the previous example on just the value bits. In this case, we need only perform the subtraction where the two inputs are either both negative or both non-negative. This avoids the arithmetic overflow condition.
Since the size of int strictly speaking is unknown at run time, we use std::numeric_limits<int>::max() as a convenient mask for the value bits. The mask of the sign bit is simply the bit-wise negation of the value bits.
Turning to the actual expression for <=, we factor out the bit-wise mask sm of the sign bit in each of the sub-expressions and push the operation to the outside of the expression. The first term of the logical expression x & ~y is true when x is negative and y is non-negative. The first factor of the next term ~(x ^ Y) is true when both are negative or both are non-negative. The second factor ~((y & vm) + ~(x & vm) + 1)) is true when y - x is non-negative, in other words x <= y, ignoring the sign bit. The two terms are or'd, so using c++ logical expression syntax we have:
x < 0 && y >= 0 || (x < 0 && y < 0 || x >= 0 && y >= 0) && y - x >= 0
The !! outermost operators convert the raised sign bit to a 1. Finally, here is the Modern C++ templated constexpr version:
template<typename T>
constexpr T isLessOrEqual(T x, T y)
{
using namespace std;
// compile time check that type T makes sense for this function
static_assert(is_integral<T>::value && is_signed<T>::value, "isLessOrEqual requires signed integral params");
T vm = numeric_limits<T>::max();
T sm = ~vm;
return !! ((x & ~y | ~(x ^ y) & ~((y & vm) + ~(x & vm) + 1)) & sm);
}
Really enjoyed Yanagar1's answer, which is very easy to understand.
Actually we can remove those shift operators and use De Morgan's laws, which reduce the number of operators from 15 to 11.
long isLessOrEqual(long x, long y) {
long sign = (x ^ y); // highest bit will be 1 if different sign
long diff = sign & x; // highest bit will be 1 if diff sign and neg x
long same = sign | (y + (~x + 1)); // De Morgan's Law with the following ~same
// highest bit will be 0 if same sign and y >= x
long result = !!((diff | ~same) & 0x8000000000000000L); // take highest bit(sign) here
return result;
}
Here is my implementation(spend around 3 hours...)
int
isLessOrEqual(int x, int y)
{
int a = y + ~x + 1;
int b = a & 1 << 31 & a; // !b => y >= x, but maybe overflow
int c = !!(x & (1 << 31)) & !(y & (1 << 31)); // y > 0, x < 0
int d = !(x & (1 << 31)) & !!(y & (1 << 31)); // x > 0, y < 0
int mask1 = !c + ~0;
// if y > 0 && x < 0, return 1. else return !b
int ans = ~mask1 & !b | mask1 & 1;
int mask2 = !d + ~0;
// if y < 0 && x > 0, return 0, else return ans
return ~mask2 & ans | mask2 & 0;
}
y - x == y + ~x + 1
a & 1 << 31 & a is simplify from !(!(a & (1 << 31)) | !a)
The logic is:
if `y > 0 && x < 0`
return true
if `x > 0 && y < 0`
return false
return y >= x
Why not just y >= x directly? because overflow may happen. So I have to early return to avoid overflow.
Inspired by Yanagar1's answer, here's my implementation:
int isLessOrEqual(int x, int y) {
int indicator = !((y + (~x + 1)) >> 31); // negation of the result of y - x, 0 when y < x, -1 when y >= x
int xsign = x >> 31; // -1 when x < 0, 0 when x >= 0
int ysign = y >> 31; // -1 when y < 0, 0 when y >= 0
int xbool = !xsign; // 0 when x < 0, 1 when x >= 0
int ybool = !ysign; // 0 when y < 0, 1 when y >= 0
int result = (!(xbool ^ ybool)) & indicator;
return result | (ybool & !xbool);
}
Explanation: Adding 2's complement negation of x (~x + 1) to y is essentially calculating y - x, then logical negate the sign bit of the result, we can have 0 when y < x, and 1 when y >= x. But there are potential overflow cases (overflow cannot happen when y and -x have opposite signs, that is, when y and x have same signs):
|-----------|------------------------|------------------------|
| | y > 0 | y < 0 |
|-----------|------------------------|------------------------|
| x > 0 | ok | overflow when y = TMin |
|-----------|------------------------|------------------------|
| x < 0 | overflow when x = TMin | ok |
|-----------|------------------------|------------------------|
so we need to be careful when the signs are different.
Might my solution is stupid.
int isLessOrEqual(int x, int y) {
/*
* A: sign bit of x B: sign bit of y C:A == B Result Rearrange the result(Expeced)
* 0 0 1 y - x >= 0 (y + (~x+1) >= 0) & 1 | 0 => (y + (~x+1) >= 0) & C | !(B | C)
* 0 1 0 0 (y + (~x+1) >= 0) & 0 | 0 => (y + (~x+1) >= 0) & C | !(B | C)
* 1 0 0 1 (y + (~x+1) >= 0) & 0 | 1 => (y + (~x+1) >= 0) & C | !(B | C)
* 1 1 1 y - x >= 0 (y + (~x+1) >= 0) & 1 | 0 => (y + (~x+1) >= 0) & C | !(B | C)
* But, minus operator is illegal. So (y - x) placed by (y + (-x)).
* You know -x == (~x + 1).
* If we know *x* and *y* have different sign bits, the answer is determinated and the (y-x >= 0) was useless.
* finally, the work like designing digital circuit. produce a final expression.
*/
int A = (x >> 31) & 1;
int B = (y >> 31) & 1;
int C = !(A ^ B);
int greatOrEqual0 = (!(((y + (~x + 1)) >> 31) ^ 0));
return (greatOrEqual0 & C) | !(B | C);
}
So I'm doing a code that converts decimals to binary. I just want my binary number to be in 8 bits. Any suggestions?
#include <stdio.h>
#include <stdlib.h>
using namespace std;
long decimalToBinary(long n);
int main() {
long decimal;
printf("Enter a decimal number: ");
scanf_s("%d", &decimal);
printf("Binary number = ") << decimalToBinary(decimal);
return 0;
}
long decimalToBinary(long n) {
int remainder;
long binary = 0, i = 1;
while (n != 0) {
remainder = n % 2;
n = n / 2;
binary = binary + (remainder*i);
i = i * 10;
}
return binary;
}
long decimalToBinary(long n) {
return n & 0xFF;
}
or (n & 0xFF00) >> 8 or (n & 0xFF0000) >> 16 or (n & 0xFF000000) >> 24. Depends on which 8 bits you want.
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
}
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.