Integer as an condition in C++'s " :?" operator - c++

So , for my exam I have to evaluate some C++ expressions.
Here s the expression :
float x=3<<2>>1?4.:.5?6:7>8;
Can someone explain it with words because I can t understand it.
So , I have to convert 3 to binary and shift it 2 bits. But After conversion the result is 11. I may add the bit sign so it becomes 011. And after the bit sign I can add as many 0's as i need and so 3<<2-> 01100. But after that I can't understand a thing.. Where s the condition on the conditional operator ?: because I can't see any?
Thank you in advice for helping me solve this out :)

Let's format this a little better:
float x = (3 << 2) >> 1 ? 4. :
.5 ? 6 :
(7 > 8);
Or even better:
float x;
if( 3<<2>>1 ) {
x = 4.;
} else if( .5 ) {
x = 6;
} else {
x = 7 > 8;
}
Walking through the evaluation of 3 << 2 >> 1:
(3 << 2) >> 1 =>
(b0011 << 2) >> 1 =>
b1100 >> 1 =>
b0110 =>
6
Since 6 is a nonzero value (which evaluates to true in C++) x will have the value 4.

The expression is
3<<2>>1?4.:.5?6:7>8
Let's add some spaces and parens:
((3 << 2) >> 1) ? 4. : (.5 ? 6 : (7 > 8))
Shifting by 1 is just multiplying by 2. Shifting by 2 is multiplying by 2, twice.
So 3 << 2 is 12.
12 >> 1 divides by 2, so that's just 6.
As a condition, all integers (except 0) are true, so this simply returns 4.0.

Related

0 < res <= (1 << 31) -1 - What does this mean?

This statement checks whether a number is 32 bits.
0 < res <= (1 << 31) -1
I can't seem to understand how, can someone help understand this bit shift syntax?
Well, lets begin with an example:
1 in binary is 1
2 in binary is 10
4 in binary is 100
We can see that we need to 'add' an 0 at the end of each number to multiply by 2 and in most language we can do this with this syntax: number << 1
Here we are saying that we add a 1 time a 0 to the left. number >> 1 and here we add 1 time a 0 to the right.
So 1 << 31 means 1 * 2 * 2 * 2 ... 31 times which means 2^31 (so 32 bits)

Invert 2 bit number: is this correct?

I have a 2 bit number x stored in a single byte, and I would like to invert it, so that 0 is transformed to 3, 1 to 2, 2 to 1 and 3 to 0.
Isx^3be the correct way of doing this?
Also, for arbitrary N bit number x, will x^((1<<N)-1) be correct ?
x^3 is good for two bit numbers. If you have 4 bit numbers, use x ^ 15, or write it in hex, x ^ 0x0f if you want.
No, x^(N-1) will not work. What will work is x^(pow(2,N)-1)
Code :
((~x)&(0x3))
Test Code (Same piece of code should work in C++ too):
public static void main(String[] args) {
// TODO Auto-generated method stub
//System.out.println("Hello");
for(int i=0; i<=3; i++) {
System.out.println("Complement of " + i + " is " + (~i & 0x3));
}
}
Result:
Complement of 0 is 3
Complement of 1 is 2
Complement of 2 is 1
Complement of 3 is 0

What does this expression calculate

Suppose X and Y are two positive integers and Y is a power of two. Then what does this expression calculate?
(X+Y-1) & ~(Y-1)
I found this expression appearing in certain c/c++ implementation of Memory Pool (X represents the object size in bytes and Y represents the alignment in bytes, the expression returns the block size in bytes fit for use in the Memory Pool).
&~(Y-1) where Y is a power of 2, zeroes the last n bits, where Y = 2n: Y-1 produces n 1-bits, inverting that via ~ gives you a mask with n zeroes at the end, anding via bit-level & zeroes the bits where the mask is zero.
Effectively that produces a number that is some multiple of Y's power of 2.
It can maximally have the effect of subtracting Y-1 from the number, so add that first, giving (X+Y-1) & ~(Y-1). This is a number that's not less than X, and is a multiple of Y.
It gives you the next Y-aligned address of current address X.
Say, your current address X is 0x10000, and your alignment is 0x100, it will give you 0x10000. But if your current address X is 0x10001, you will get "next" aligned address of 0x10100.
This is useful in the scenario that you want your new object always to be aligned to blocks in memory, but not leaving any block unused. So you want to know what is the next available block-aligned address.
Why don't you just try some input and observe what happens?
#include <iostream>
unsigned compute(unsigned x, unsigned y)
{
return (x + y - 1) & ~(y - 1);
}
int main()
{
std::cout << "(x + y - 1) & ~(y - 1)" << std::endl;
for (unsigned x = 0; x < 9; ++x)
{
std::cout << "x=" << x << ", y=2 -> " << compute(x, 2) << std::endl;
}
std::cout << "----" << std::endl;
std::cout << "(x + y - 1) & ~(y - 1)" << std::endl;
for (unsigned x = 0; x < 9; ++x)
{
std::cout << "(x=" << x << ", y=2) -> " << compute(x, 2) << std::endl;
}
return 0;
}
Live Example
Output:
First set uses x in [0, 8] and y is constant 2. Second set uses x in [0, 8] and y is constant 4.
(x + y - 1) & ~(y - 1)
x=0, y=2 -> 0
x=1, y=2 -> 2
x=2, y=2 -> 2
x=3, y=2 -> 4
x=4, y=2 -> 4
x=5, y=2 -> 6
x=6, y=2 -> 6
x=7, y=2 -> 8
x=8, y=2 -> 8
----
(x + y - 1) & ~(y - 1)
(x=0, y=2) -> 0
(x=1, y=2) -> 2
(x=2, y=2) -> 2
(x=3, y=2) -> 4
(x=4, y=2) -> 4
(x=5, y=2) -> 6
(x=6, y=2) -> 6
(x=7, y=2) -> 8
(x=8, y=2) -> 8
It's easy to see the output (i.e., result right of ->) is always a multiple of y such that the output is greater than or equal to x.
First I assume that X and Y are unsigned integers.
Let's have a look at the right part:
If Y is a power of 2, it is represented in binary by one bit to 1 and all the others to 0. Example 8 will be binary 00..01000.
If you substract 1 the highest bit will be 0 and all the bits to its right will become 1. Example 8-1= 7 and in binary 00..00111
If you ~ negate this number you will make sure that all highest bit (including the original one will turn to 1 and the lovest to 0. Example: ~7 will be 11..11000
Now if you do a binary AND (&) with any number, you will set to 0 all the lower bits, in our example, the 3 lower bits. THe resulting number is hence a multiple of Y.
Let's look at the left side:
We've already analysed Y-1. In our example we had 7, that is 00..00111
If you add this to any number, you make sure that the result is greater than or equal to Y. Example with 5: 5+7=12 so 00..01100 and example with 10: 10+7=17 so 00..10001
If you then perform the AND, you'll erase the lower bits. so in our example with 5, we come to 00..01000 = 8 and in our example with 10 we get 00..10000 16.
Conclusion, it's the smallest multiple of Y wich is greater or equal to X.
Let's break it down, piece by piece.
(X+Y-1) & ~(Y-1)
Let's suppose that X = 11 and Y = 16 in accordance with your rules and that the integers are 8 bits.
(11+16-1) & ~(16-1)
Do the Addition and Subtraction
(26) & ~(15)
Translate this into binary
(0001 1010) & ~(0000 1111)
~ means not or to invert the zeros and ones
(0001 1010) & (1111 0000)
& means only to take the bits that are both ones
0001 0000
convert back to decimal
16
other examples
X = 78, Y = 32 results in 96
X = 25, Y = 64 results in 64
X = 47, Y = 16 results in 48
So, it would seem to me that the purpose of this is to find lowest multiple of Y that is equal to or greater than X. This could be used for finding the start/end address of a block of memory, or it could be used for positioning items on the screen, or any number of other possible answers as well. But without context and possibly even a full code example. There's no guarantee.
(X+Y-1) & ~(Y-1)
x = 7 = 0b0111
y = 4 = 0b0100
x+y-1 = 0b1010
y-1 = 3 = 0b0011
~(y-1) = 0b1100
(x+y-1) & ~(y-1) = 0b1000 = 8
--
x = 12 = 0b1100
y = 2 = 0b0010
x+y-1 = 13 = 0b1101
y-1 = 1 = 0b0001
~(y-1) = 0b1110
(x+y-1) & ~(y-1) = 0b1100 = 12
(x+y-1) & ~(y-1) is the smallest multiple of y greater than or equal to x
It seems provides a specified alignment of a value for example of a memory address (for example when you want to get the next aligned address).
For example if you want that a memory address would be aligned at the paragraph bound you can write
( address + 16 - 1 ) & ~( 16 - 1 )
or
( address + 15 ) & ~15
or
( address + 15 ) & ~0xf
In this case all bits before 16 will be zeroed.
This part of expression
( address + alignment - )
is used for rounding.
and this part of expression
~( alignment - 1 )
is used to build a mask thet zeroes low bits.

Modulus to account for negative numbers

I'm trying to write a code for modulus, but when I do it for negative numbers I don't get the right result, my code:
double mod (double X, double Y)
{
double result = X;
if (X>0){
do
{
result = result - Y;
}while(result >= Y);
}
if (X<0){
do
{
result = result + Y;
}while(0 >= result);
}
}
When you do something like mod(-5,2) it should return -1 but it returns 1, why does it return 1 when it can't be greater than 0?
In my mind I thought it works like -5 + 2 = -3 + 2 = -1. For positive it would be 5 - 2 = 3 - 2 = 1.
Thanks.
EDIT: I am trying to do this without using CMATH using my own math library.
EDIT: My return result is in a later part of the program and does show output. This just a block of the entire program itself.
Examine this part of code only:
if (X<0){
do
{
result = result + Y;
}while(0 >= result);
}
Let's say that X is -5, and result is 0.
do loop will be executed:
1. pass - result = -3
2. pass - result = -1
3. pass - result = -1 + 2 = 1
3. pass will be executed as result from 2. pass is still less than zero.
You need to change your loop condition to while(0 >= result + Y)
You are missing
return result;
consider the integer sequence
-7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7
when taking mod(5,2) we are taking multiple of 2 less than or equal to 5 then return difference with 5. ie here 1 (5-4)
for negative numbers according to this concept
for mod(-5, 2). number which is lesser than -5 that is divisible by 2 is -6(not -4; -4 > -5). and its difference is (-5 - -6) which is 1.
That is what happening in your code

Multiple of 5 checking

How is this code working for multiple of 5
bool isMultipleof5(int n)
{
/* If n is a multiple of 5 then we make sure that last
digit of n is 0 */
if ( (n&1) == 1 )
n <<= 1;
float x = n;
x = ( (int)(x*0.1) )*10;
/* If last digit of n is 0 then n will be equal to (int)x */
if ( (int)x == n )
return true;
return false;
}
It first makes n divisable by 2.
Next, it checks if it is divisable by 10 by multiplying with 0.1 and again with 10. The idea that if it is divisable by 10, you will get back to the original, and only then.
So, if the modifies n is divisable by 10 - it is certainly divisable by 5 as well, and since modified n is always divisable by 2, if it is divisable by 5 it will be divisable by 10, and the algorithm works.
NOTE: This is very unsuggested and especially might break with large values due to floating point precision issues. using the % operator should be prefered: return (n % 5) == 0
This is how the code works with some examples.
if ( (n&1) == 1 ) //Checks if the number is odd
n <<= 1; //Multiplies the number by 2 if odd
x = ( (int)(x * 0.1) //Divides the number 10 then truncates any decimal places
* 10 ) //Multiplies it back by 10
if ( (int)x == n ) //If the floating point value equals the (semi) original value its divisible by 5
return true;
return false; //Other wise false
Example:
15 & 1 == 1 //15 is odd
15 <<= 1; //n is now 30
30 / 10 = 3;
3 * 10 = 30; //x is now 30
30 == 30 //15 is a multiple of 5
17 & 1 == 1 //17 is odd
17 <<= 1; //n is now 34
34 / 10 = 3.4;
((int)3.4 = 3) * 10 = 30; //x is now 30
30 != 34 //17 is not a multiple of 5.
As others said though just simply use the mod operator %.
This is how it works:
Double the number. Now anything ending in 5 will be divisible 10 (and also divisible by 5). n <<= 1; (the check for oddness is unnecessary (n&1) == 1)
Divide it by 10, and cast away the fractional part. (int)(x*0.1)
Multiply it by 10, so now we have the same number as in step 1 only if the number in step 1 was already divisible by 10.
The use of floating point to divide by 10 makes this algorithm dangerous and probably incorrect for large values.
Try this
bool isMultipleof5(int n)
{
return (n%5) == 0;
}
A simpler way would be
bool isMultipleof5(int n)
{
return 0 == ( n % 5 ) ;
}
#define IS_MULTIPLE_OF_5(n) (((n)%5) ? 0 : 1)
I'd agree that (n % 5) == 0 would be an ideal solution, but that wasn't really the question.
This code works because it first checks if the input is odd. If it is, it multiplies by two. Since all odd multiples of 5 end with a 5, multiplying by 2 gives a number that ends with 0.
Then it checks if the last digit is 0. This can only happen if it started as a 0 (i.e. was even, we didn't change it) or if it was odd and ended in a 5 (we multiplied by 2). So, if it ends in 0 then the input must have been divisible by 5.
I'd add that this is also an awkward way to check the value of the last digit. I'd suggest n % 10 == 0 instead, but like others mentioned... you could have just used n % 5 == 0 in the first place ;).