How to zero out bottom n bits in a C unsigned int? - c

I am trying to write my own C floor function. I am stuck on this code detail. I would just like to know how I can zero out the bottom n bits of an unsigned int.
For example, to round 51.5 to 51.0, I need to zero out the bottom 18 bits, and keep the top 14. Since it's a floor function, I want to make a mask to zero out the bottom (23 minus exponent) bits from the float representation. I know how to make a mask for individual cases like that, but I'm not sure how to code it so that it will work for all. Please help.

A much simpler way is doing just this:
value = (value >> bits) << bits
because the shift left will fill it in with zeroes, not whatever was in there.

Shift a number left N bits. Subtract one. Invert the bits. And with the number you need to mask.
1 << 14 = 00000000000000000010000000000000
-1 = 00000000000000000001111111111111
~ = 11111111111111111110000000000000
When you and with this, a 1 in the mask will preserve the input, and 0 in the mask will set the result to 0.

Related

Finding if a value falls within a range, using bitwise operators in C

So i am working on this method, but am restricted to using ONLY these operators:
<<, >>, !, ~, &, ^, |, +
I need to find if a given int parameter can be represented using 2's complement arithmetic in a given amount of bits.
Here is what I have so far:
int validRange(int val, int bits){
int minInRange = ~(1<<(bits + ~0 ))+1; //the smallest 2's comp value possible with this many bits
int maxInRange = (1<<(bits+~0))+~0; //largest 2's comp value possible
..........
}
This is what I have so far, and all I need to do now is figure out how to tell if minInRange <= val <=maxInRange. I wish I could use the greater than or less than operator, but we are not allowed. What is the bitwise way to check this?
Thanks for any help!
Two's complement negative numbers always have a '1' in their high bit.
You can convert from negative to positive (and vice versa) by converting from FF -> 00 -> 01. That is, invert the bits, add 1. (01 -> FE -> FF also works: invert the bits, add 1)
A positive number can be represented if the highest set bit in the number is within your range. (nbits - 1: 7 bits for an 8 bit signed char, etc.)
I'm not sure if your constraints allow you to use arrays. They would speed up some things but can be replaced with loops or if statements.
Anyway, if 1 << (NUM_INT_BITS-1) is set on your input, then it's negative.
Invert, add one.
Now, consider 0. Zero is a constant, and it's always the same no matter how many bits. But if you invert 0, you get "all the bits" which changes by architecture. So, ALL_BITS = ~0.
If you want to know if a positive number can be represented in 2 bits, check to see if any bits greater than or equal to bit 2 are set. Example:
two_bits = 0b00000011
any_other_bits = ~two_bits # Result: 0b11...11100
if positive_number & any_other_bits
this number is too fat for these bits!
But how do you know what ~two_bits should be? Well, it's "all set bits except the bottom however-many". And you can construct that by starting with "all set bits" and shifting them upwards (aka, "left") however-many places:
any_other_bits = ~0 << 2 # where "2" is the number of bits to check
All together now:
if (val & ((unsigned)INT_MAX + 1))
val = ~val + 1;
mask = ~0 << bits;
too_wide = val & mask;
return !too_wide;
To test if a number can be represented in a N-bit 2s compliment number: Simply test that either
The number bitwise-and'ed with the compliment of a word with the low (N-1) bits set is equal to zero
OR The high InputBitWidth-(N-1) bits of the number are 1s.
mask=(1<<(bits-1))-1; return ( !(val&mask) | !((val&~mask)^~mask) );

Bitwise multiplication and division not working with large numbers

I'm trying to get this problem to work where I have to multiply 3/8 in bit and then round towards zero.
So far I have this
((((x<<1)+x)>>3)+((x>>31)&1));
The idea behind it is that the first part takes x and shifts it left 1 and adds x to get the multiplied by 3 effect and then shifts right 3 to get the divide by 8 part. Then I would add 1 if it is negative by testing to see if the sign bit is 1 (1&1 = 1) or 0 (0&1 = 0). My code won't work though, the tests are off.
Any ideas what I am doing wrong?
The left shifts that you use in effect shifts the individual bits as an unsigned integer so that you could wind up losing the sign bit. That is not what it sounds like you want. Try the multiplication to see what you should be getting against the bit shift to see what you are getting.
x *= 3.0/8.0;
Note the manual entry below showing that if the signed bit is affected the result is undefined
Left shift
The left-shift operator causes the bits in shift-expression to be
shifted to the left by the number of positions specified by
additive-expression. The bit positions that have been vacated by the
shift operation are zero-filled. A left shift is a logical shift (the
bits that are shifted off the end are discarded, including the sign
bit). For more information about the kinds of bitwise shifts, see
Bitwise shifts.
The following example shows left-shift operations using unsigned
numbers. The example shows what is happening to the bits by
representing the value as a bitset. For more information, see bitset
Class.
If you left-shift a signed number so that the sign bit is affected, the result is undefined. The following example shows what happens in
Visual C++ when a 1 bit is left-shifted into the sign bit position.
#include <iostream>
#include <bitset>
using namespace std;
int main() {
short short1 = 16384;
bitset<16> bitset1{short2};
cout << bitset1 << endl; // 0100000000000000
short short3 = short1 << 1;
bitset<16> bitset3{short3}; // 16384 left-shifted by 1 = -32768
cout << bitset3 << endl; // 100000000000000
short short4 = short1 << 14;
bitset<16> bitset4{short4}; // 4 left-shifted by 14 = 0
cout << bitset4 << endl; // 000000000000000
}
You are overflowing your format by testing with the most negative number and then trying to multiply it to a larger (i.e., even more negative) number.
There are various ways to fix this.
Use something larger like int64.
Use a second value to hold the overflow.
Split the value in half and then compute it as a polynomial.
For the one test case, you could divide first and then multiply, and it would "work", but it would fail for all the cases where you then lose bits off the right side.

C: Extracting a specific set of bits? Need help explaining a particular example

Question:
A device is connected to a computer that can return various
temperatures related to the weather. The GetTemps function returns the
daily high temperature in bits 20–29, the daily low temperature in
bits 10–19, and the current temperature in bits 0–9, all as 10-bit
integers. In the following program fragment, lines 8 and 9 are
incomplete. They should store the high temperature in highTemp and the
current temperature in currTemp, so that these temperatures can be
printed in line 10. Please complete lines 8 and 9, and implement code
efficiently
#include <stdio.h>
// Line 1
// Line 2
int GetTemps(void);
// Line 3
// Line 4
int main( ) {
// Line 5
int w, highTemp, currTemp;
// Line 6
w = getTemps( );
// Line 7
highTemp = <QUESTION 1>
// Line 8
currTemp = <QUESTION 2>
// Line 9
printf ( "High: %d\nCurrent: %d\n", highTemp, currTemp)
// Line 10
return 0;
}
The answers are
highTemp = w>>20
currtemp = w<<20
The correct right shift (for highTemp) and bitmask (for lowTemp)
operations.
As given by my class TA
Can someone explain this answer to me? I think I understand how hightemp is w>>20, but if w is a 30-bit int[30...0] then wouldn't a bitshift to the left push bits 10 to 0 to the left and effectively multiply it by 2^20? That seems too large to me.
Edit: The exact answer:
Your TA's answer is wrong. Here's how to solve the problem.
When several fields are packed into a single value, it's safest to isolate the bits you want first (by masking). For example, given that the high temp is in bits 20-29, we need a mask to isolate those bits.
const int high_mask = 0x3FF00000; // 10-bit integer in bits 20-29
const int high_bits = w & high_mask; // select the bits we care about
To convert that to a temperature, we need to shift the result so that bit 20 is int bit 0.
const int high_temp = high_bits >> 20; // shift them "down"
But this is not entirely right! We haven't accounted for negative temperatures. An arithmetic right-shift will preserve the sign of the value, but we've zero-ed out the high bits (of the 32-bit integer). Even if we hadn't masked those bits out, the problem doesn't say what values are in those top bits, so we shouldn't make assumptions.
The easiest way to account for the sign is to first shift left, so that our top bit is in the top position. Then, we when shift right, the processor will do the appropriate sign extension. Assuming ints are 32 bits ...
const int high_temp = (high_bits << 3) >> 23; // shift down, preserving the sign
Note that the right shift value must account for the left shift we did first.
(Technically, if we shift to lop off the top bits and then shift the other way to lop off the lowest bits, the masking is no longer necessary, but conceptually, it can help with comprehension.)
Also note that precedence with bit-wise operators can be surprising. So if you try to combine these steps into a single expression, you'll likely have to add some parentheses.
A similar process can extract the current temperature (and any int value embedded in a larger integral type). You just have to tweak the constants.

Homework - C bit puzzle - Perform % using C bit operations (no looping, conditionals, function calls, etc)

I'm completely stuck on how to do this homework problem and looking for a hint or two to keep me going. I'm limited to 20 operations (= doesn't count in this 20).
I'm supposed to fill in a function that looks like this:
/* Supposed to do x%(2^n).
For example: for x = 15 and n = 2, the result would be 3.
Additionally, if positive overflow occurs, the result should be the
maximum positive number, and if negative overflow occurs, the result
should be the most negative number.
*/
int remainder_power_of_2(int x, int n){
int twoToN = 1 << n;
/* Magic...? How can I do this without looping? We are assuming it is a
32 bit machine, and we can't use constants bigger than 8 bits
(0xFF is valid for example).
However, I can make a 32 bit number by ORing together a bunch of stuff.
Valid operations are: << >> + ~ ! | & ^
*/
return theAnswer;
}
I was thinking maybe I could shift the twoToN over left... until I somehow check (without if/else) that it is bigger than x, and then shift back to the right once... then xor it with x... and repeat? But I only have 20 operations!
Hint: In decadic system to do a modulo by power of 10, you just leave the last few digits and null the other. E.g. 12345 % 100 = 00045 = 45. Well, in computer numbers are binary. So you have to null the binary digits (bits). So look at various bit manipulation operators (&, |, ^) to do so.
Since binary is base 2, remainders mod 2^N are exactly represented by the rightmost bits of a value. For example, consider the following 32 bit integer:
00000000001101001101000110010101
This has the two's compliment value of 3461525. The remainder mod 2 is exactly the last bit (1). The remainder mod 4 (2^2) is exactly the last 2 bits (01). The remainder mod 8 (2^3) is exactly the last 3 bits (101). Generally, the remainder mod 2^N is exactly the last N bits.
In short, you need to be able to take your input number, and mask it somehow to get only the last few bits.
A tip: say you're using mod 64. The value of 64 in binary is:
00000000000000000000000001000000
The modulus you're interested in is the last 6 bits. I'll provide you a sequence of operations that can transform that number into a mask (but I'm not going to tell you what they are, you can figure them out yourself :D)
00000000000000000000000001000000 // starting value
11111111111111111111111110111111 // ???
11111111111111111111111111000000 // ???
00000000000000000000000000111111 // the mask you need
Each of those steps equates to exactly one operation that can be performed on an int type. Can you figure them out? Can you see how to simplify my steps? :D
Another hint:
00000000000000000000000001000000 // 64
11111111111111111111111111000000 // -64
Since your divisor is always power of two, it's easy.
uint32_t remainder(uint32_t number, uint32_t power)
{
power = 1 << power;
return (number & (power - 1));
}
Suppose you input number as 5 and divisor as 2
`00000000000000000000000000000101` number
AND
`00000000000000000000000000000001` divisor - 1
=
`00000000000000000000000000000001` remainder (what we expected)
Suppose you input number as 7 and divisor as 4
`00000000000000000000000000000111` number
AND
`00000000000000000000000000000011` divisor - 1
=
`00000000000000000000000000000011` remainder (what we expected)
This only works as long as divisor is a power of two (Except for divisor = 1), so use it carefully.

Help to begin in assigning specific bits

So I have a problem for my class that I am having trouble getting started on. I am not asking people to do the problem for me, I just would like any nudge in the right direction. I need to create a function in C that when given any 32 bit integer it returns an integer where every 4th bit is set to a 1 starting at the least sig bit. I understand what it is supposed to look like in the end, but getting started I am lost on. We are not allowed to use any for loops or conditionals, just the standard bitwise and logical operators(! ~ & ^ | + << >>). Once again, I am not asking anyone to do this for me, I just would like some help in getting me thinking on the right track. I have seen some of the other posts on here and on other pages, but none seem to click. I understand that you can bitshift a 1 into a certain place x<<3 but going beyond that I am stuck. Any help would be appreciated.
int get_int_with_every_fourth_bit_set()
{
return 0x88888888;
}
Ok, that was mostly facetious. Here's a list of what the bitwise operators do:
bitwise NOT (~): Toggle a bit, 0 to 1 and 1 to 0
AND (&): Set a bit if the bit in that position is set in both operands
OR (|): Set a bit if the bit in that position is set in either operand
XOR (^): Set a bit if exactly one bit in that position is set between the two operands
Bitwise shift (<< and >>): Move each bit over the specified amount in the given direction. When shifting left, zeros are added to the least significant bit. When shifting right, a zero will be added if the value is either unsigned or positive.
Here are some bitwise tricks that are good to know:
A bitwise shift left by one is the same as multiplying by two. A bitwise shift right by one is the same as dividing by two, and rounding down.
All powers of two have exactly one 1 bit. To see if a number is a power of two, you can do this:
return !(x & (x - 1)) && x
As an example, say x = 16, which is a power of two. Then, x - 1 = 15, so the values to be ANDed are 00010000 and 00001111. Since each bit position has a zero in at least one of the two operands, the result is zero. !0 is true, so check to see if x != 0. Since 16 != 0, the statement returns true. If you try it with a number that is not a power of two and not zero, then the x & (x - 1) check will always be true. So cool!
Another tip: since 0 ^ 0 = 0 and 1 ^ 1 = 0, you can use XOR to see what bits have changes. For example, if you have two bytes and want to see the bits that changed between then, the XOR of the two bytes will give you a 1 in the position of all bits that have changed.
Can you write down (in hex) the 32 bit integer that has every 4th bit set to 1, and all other bits set to 0?
Now, is there an operation you can apply to your input and this magic number, which sets every 4th bit of the input to 1, but leaves the other bits alone?
Check out bitmasking.
...Therefore, to make sure a bit is on, OR can be used with a 1. To leave a bit unchanged, OR is used with a 0.
So the mask for your case (leaving other bits unchanged) would be:
Binary: 10001000100010001000100010001000
Hex: 88888888

Resources