Why do x+0 and x|0 have different results? - c++

Why do x+0 and x|0 have different results?
Below is my code.
My environment is WSL (Debian Sid) + GCC 10.2.1.
#include <stdio.h>
/**
* Do rotating left shift. Assume 0 <= n < w
* Examples when x = 0x12345678 and w = 32:
* n = 4 -> 0x23456781, n = 20 -> 0x67812345
*/
unsigned rotate_left(const unsigned x, const int n)
{
const int w = sizeof(unsigned) << 3;
return (x << n) + (x >> (w - n));
}
int main()
{
int x = 0x12345678;
printf("n = 4, %#x -> %#x\n", x, rotate_left(x, 4));
printf("n = 20, %#x -> %#x\n", x, rotate_left(x, 20));
printf("n = 0, %#x -> %#x\n", x, rotate_left(x, 0));
}
when n = 0, the result is 0x2468acf0.
when i replace return (x << n) + (x >> (w - n)) with return (x << n) | (x >> (w - n)), i get 0x12345678.

If x is an integer type with at most 32 bits, then x>>32 is Undefined Behaviour, which means that the result can be absolutely anything (and it can be a different anything in different programs). (Also true of x<<32.) [Note 1]
From §6.5.7 para 3 of the C standard, concerning << and >> operators, emphasis added:
If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
As a result, your rotate function won't work if n <= 0 or n >= w, and you should test for those cases rather than assume they won't occur (since they obviously will).
Notes
In practice, on Intel hardware (and probably others), a shift by the width of the operand is a no-op, not "clear to 0". So x>>32 is x, as is x<<0, and thus the sum is twice x, while the bitwise or is exactly x. But you cannot rely on that fact, because it's Undefined Behaviour, and compiler optimizations might result in other arbitrary results.

Related

Why do I need to convert my two variables from int to long long int in the provided case?

I was solving a programming question (problem 633 on Leetcode).
The below code does not run, it gives this error:
runtime error: signed integer overflow: 829921 + 2146654224 cannot be represented in type 'int'
bool judgeSquareSum(int c)
{
int h=sqrt(c),l=0;
while(l<=h)
{
long long sum=l*l+h*h;
if(sum>c)
{
h--;
}
else
if(sum<c)
l++;
else
return true;
}
return false;
}
Whereas the below code runs perfectly. The only difference is, variables l and h are of long long type as compared to int type in the above code.
To specify - l and h cannot have values greater than INT_MAX neither l*l and h*h can be greater than INT_MAX.
bool judgeSquareSum(int c) {
long long l = 0, h = sqrt(c);
while (h >= l) {
long long xxxx = l * l + h * h;
if (xxxx > c) {
h--;
} else if (xxxx < c) {
l++;
} else {
return true;
}
}
return false;
}
The error message is telling you precisely what the problem is:
signed integer overflow: 829921 + 2146654224 cannot be represented in type 'int'
You're trying to add the values 829921 and 2146654224 and the result (which should be 2147484145) does not fit in an int. This tells us that you're almost certainly running on a machine where INT_MAX is 231-1 or 2147483647
This would appear to be coming from the line
long long xxxx = l * l + h * h;
where l and h both have type int so the expression l * l + h * h will be evaluated as type int. The fact that the value will be used to initialize a value of type long long is irrelevant -- in C (and C++) the type and precision of expression is determined solely from the types of the operands and not from how the result will be used.
You can avoid overflow by being careful with your operations. Since you know that c fits in an int and h and l are always <= sqrt(c), so h * h and l * l don't overflow, it's only the sum that overflows. So you can rewrite your code as:
bool judgeSquareSum(int c) {
int l = 0, h = sqrt(c);
while (h >= l) {
int xxxx = l * l - c + h * h;
if (xxxx > 0) {
h--;
} else if (xxxx < 0) {
l++;
} else {
return true;
}
}
return false;
}
and not need larger types
long long has a size of at least 64 bits. int has at least a size of 16 bits. Therefore not all numbers that you can represent in long long can also be represented as int without value loss, hence the need for the larger type. See more here: https://en.cppreference.com/w/cpp/language/types

Negating INT_MIN in CPP

The question I am trying to solve is:
Implement pow(x, n), which calculates x raised to the power n (Leetcode problem 50)
I have the following code:
class Solution {
public:
double myPow(double x, int n) {
if (n == 0) {
cout << "in last";
return 1;
} else if (n < 0) {
x = 1 / x;
return myPow(x, -n);
} else if (n % 2 == 0) {
double y;
cout << "in even";
y = myPow(x, n / 2);
cout << "y is ";
cout << y;
return (y * y);
}
else {
cout << "in odd";
double j = myPow(x, n - 1);
cout << "j is ";
cout << x * j;
return (x * j);
}
}
};
When ran for the test case x=1.00000 and n = -2147483648. I am getting the error:
runtime error: negation of -2147483648 cannot be represented in type 'int'; cast to an unsigned type to negate this value to itself (solution.cpp)
Why do I get this and how shall I solve it? TIA
If you want to support -2147483648 then you need to use a long long type, not an int.
If int is a 32 bit 2's complement type then 2147483648 is actually a long or a long long type.
There are no such things as negative literals in C++ (-2147483648 is a compile time evaluable constant expression consisting of the negation of the literal 2147483648), so -2147483648 is either a long or a long long type too. This is why you'll often see INT_MIN defined as -2147483647 - 1.
If the above is the case on your platform then the behaviour of your code is undefined for that input, as you are overflowing an int type.
A 4 bytes (or 32 bits) int has a range of -2,147,483,648 to 2,147,483,647, thus if you negate -2,147,483,648 you can't represent it as int.
You could try using unsigned int (which has a range of
0 to 4,294,967,295) or long long int (which a range of -(2^63) to (2^63)-1) make this negation and fit the positive value there.
I opted for a different approach and handled this case separately since it is the only value that will cause us trouble.
Add 1 to that negative value before negating it.
To compensate for that I multiplicate the base once more separately.
if (n == -2,147,483,648)
{
return (1.0/x) * myPow(1.0/x, -(n + 1));
}
The full solution
double myPow(double x, int n)
{
if (n == 0) return 1.0;
if (n < 0)
{
if (n == -2,147,483,648)
{
return (1.0/x) * myPow(1.0/x, -(n + 1));
}
return myPow(1.0/x, -n);
}
return (n % 2 == 0) ? myPow(x * x, n / 2) : x * myPow(x * x, n / 2);
}

Find a,b,n so that (a^b)%n=x

Say I choose a value for x that can be between 0 and 2147483647. (Int32.MaxValue)
I am trying to figure out how I can find values for a,b,n so that (a^b)%n=x
I already know that I can use ModPow to verify the values, but I don't know how I can find a fitting a,b and n.
#include <iostream>
/// Calculate (a^b)%n
/// \param a The base
/// \param b The exponent
/// \param n The modulo
/// \return (a^b)%n
int ModPow(int a, int b, int n) {
long long x = 1, y = a;
while (b > 0) {
if (b % 2 == 1) {
x = (x * y) % n; // multiplying with base
}
y = (y * y) % n; // squaring the base
b /= 2;
}
return x % n;
}
int main() {
int x = 1337;
// How to find a,b,n so that (a^b)%n=x
int a = ?;
int b = ?;
int n = ?;
if(x == ModPow(a,b,n))
printf("ok");
return 0;
}
int n = 2147483647
int a = ModPow(x, 9241, n);
int b = 464773;
n = 231 − 1 is a prime number. So due to Fermat's little theorem, xn mod n = x and xn − 1 mod n = 1 (unless x = 0) so x2 n − 1 mod n = x, too. 2 n − 1 = 9241 × 464773. So (x9241 mod n)464773 mod n = x. Note that you need x < n for this to work; x = 2147483647 cannot work if n is a 31 bit (i.e. signed) integer, too.
It took me a while to get here; for a long time I've had this answer messing about with Carmichael numbers and the Carmichael function before I reached this easy solution. See edit history for details.
The modulus operator:
Yields the remainder given by the following expression, where e1 is the first operand and e2 is the second: e1 – (e1 / e2) * e2
Therefor whatever the max value of x is, n must be larger. Since you're validating with n as an int and you're specifying the range: 0 and numeric_limits<int>::max() that must be an exclusive range, and for n to be an int the only possible value it can take is: numeric_limits<int>::max().
With n forced our equation effectively becomes: ab = x.
We'll need to do a check here that x is not 1, if it is b = 0 and a can be anything in our legal range so we can arbitrarily pick a = 2. But baring this:
Our requirements are:
1 < a < x and a is an int
1 < b < x and b is an int
Given x, we can search for a combination of a and b that will fit as follows:
auto a = 0.0;
auto b = 1;
if(x == 1) {
a = 2.0;
b = 0;
} else {
while((a = pow(x, 1.0 / ++b)) > 2.0) {
double dummy;
if(modf(a, &dummy) == 0.0) {
break;
}
}
}
At this point, if a >= 2.0 then there is a valid solution to the problem. Now as you as you are probably well aware, pow is a very expensive function so this will likely take a very long time to execute for larger values of x, I'd personally suggest finding an a and b for every number for which such a pair exists and storing them in a map and doing a lookup on that.
Anyway this is a demonstration of working code:
Live Example

setting bits at shifts using bitwise operators

Im trying to replicate the function
int test(int x, int y)
{
int result = 0;
int i;
for (i = y; i <= x; i++)
result |= 1 << i;
return result;
}
which takes two ints and sets a bit for each position between the two numbers. Assuming 0 <= x <= 31, and 0 <= y <= 31. For example (7, 5) will set 1 to 1110 0000 where a bit is set after shifting 5, 6, and 7 times.
Im trying to do the same thing but have been restricted to using only certain bitwise operators (~ & + <<). however am having difficulty finding a way that does not use a loop. The function should return 0 if y > x.
I believe I can replicate the or operator x|y using ~(~x & ~y).
and x^y using ~(~(~x & y) & ~(x & ~y));
http://www.tutorialspoint.com/cprogramming/c_operators.htm
If you can use - you could do it like this:
int test(int x, int y)
{
int mask1 = (1 << y) - 1;
int mask2 = (1 << (x+1)) - 1;
int result = mask1 ^ mask2;
return result;
}
Checking for y > x is left as an exercise for the reader.

Rounded power of 2 divider done with bitwise operations fails for some inputs

I wrote the following function:
int divideBy2Power(int x, int y) { return (x >> y) + (x < 0 && x << (32 - y)); }
which is supposed to compute {x / (2^y)} (rounding towards zero) in an extremely efficient manner (i.e. without branching!)
In testing it works for most inputs, but for divideBy2Power(-2, 0) it produces -1. Likewise, x=-1, y=0 produces 0 (not -1). It works for bunches of other negative numbers.
I'm on a 32-bit machine and I checked that x << 32 produces zero.
Any ideas?
You have two sources of undefined behaviour (UB), and one of implementation-defined behaviour (IDB):
x << 32 is UB for all x (assuming you have 32-bit int on your platform).
-2 << y is UB for all y.
-2 >> y is IDB for all y.
So any behaviour you observe for divideBy2Power(-2, 0) is entirely down to "chance" (for lack of a better term).
I realise that this doesn't directly answer your question, but in a sense, it doesn't matter. Invoking UB twice in one expression should be avoided at all cost; you need to find a different way to write your function.
Ah, the answer is obvious once you break down the expression:
New code:
#include <stdio.h>
int divideBy2Power(int x, int y)
{
int a = x >> y;
int b = x < 0;
int c = x << (32-y);
printf("a=%d\n", a);
printf("b=%d\n", b);
printf("c=%d\n", c);
printf("b&&c=%d\n", (b&&c));
return a + (b && c);
}
int main()
{
printf("%d\n", divideBy2Power(-2, 0));
return 0;
}
Then you clearly see that b=1, c=-2 so b&&c = 1.
Your first problem is that you're adding the result of a binary AND comparison && (not bitwise); which will be either 0 or 1. That's nonsensical, it DOES use a branch, and has other questionable logic.
Secondly, see https://stackoverflow.com/a/9874464/1110687 for an explanation of why this fails with signed numbers and what exactly is undefined behavior in this case. It's about left-shifting but it applies to right-shifting also.
Perhaps you meant
int divideBy2Power(int x, int y) { return (x >> y) + ( (x < 0)& (x << (32 - y))); }
Note the extra parentheses. The order of precedence on << and >> is often not what you expect.