I want to apply a bitmask to a number that will mimic the absolute value function for 2's complement encoded signed 32 bit integers. So far, I have
int absoluteValue(int x) {
int sign = x >> 31; //get most significant byte...all 1's if x is < 0, all 0's if x >= 0
int negated = (~x + 1) & sign; //negates the number if negative, sets to 0 if positive
//what should go here???
}
Am I going in the right direction? I'm not really sure where to go from here (mostly just how to apply a mask to keep the original positive value). I also don't want to use any conditional statements
Bizarre question. What about
return (negated << 1) + x;
So put together this makes:
int absoluteValue(int x) {
int sign = x >> 31; //get most significant byte...all 1's if x is < 0, all 0's if x >= 0
int negated = (~x + 1) & sign; //negates the number if negative, sets to 0 if positive
return (negated << 1) + x;
}
The last part
negated = (~x + 1) & sign;
is wrong, you are going to get either 1 or 0, you have to create a mask with all
first 31 bits to 0 and only the last one to either 0 or 1.
Assuming that for you target you are dealing with 32 bit integers with 2
complement, you can do this:
#include <stdio.h>
// assuming 32bit, 2 complement
int sign_inverse(int n)
{
int mask = ~n & 0x80000000U;
if(n == 0)
mask = 0;
return (~n + 1) | mask;
}
int main(void)
{
int a = 5;
int b = -4;
int c = 54;
int d = 0;
printf("sign_inverse(%d) = %d\n", a, sign_inverse(a));
printf("sign_inverse(%d) = %d\n", b, sign_inverse(b));
printf("sign_inverse(%d) = %d\n", c, sign_inverse(c));
printf("sign_inverse(%d) = %d\n", d, sign_inverse(d));
return 0;
}
but you need at least 1 if for the case of 0, because the mask for 0 is 0x80000000.
The output of this is:
$ ./b
sign_inverse(5) = -5
sign_inverse(-4) = 4
sign_inverse(54) = -54
sign_inverse(0) = 0
Please note that two's complement representation is not guaranteed, and also the behaviour of operator >> on signed values, where the result get's "filled" with 1-bits is implementation defined (cf., for example, cppreference.com/arithmetic operations):
For negative LHS, the value of LHS >> RHS is implementation-defined
where in most implementations, this performs arithmetic right shift
(so that the result remains negative). Thus in most implementations,
right shifting a signed LHS fills the new higher-order bits with the
original sign bit (i.e. with 0 if it was non-negative and 1 if it was
negative).
But if you take this for given, and if you just want to use bit wise operations and operator +, you are already going into the right direction.
The only thing is that you should take into account the mask you create ( i.e. your sign) in that you toggle the bits of x only in the case where x is negative. You can achieve this by the XOR-operator as follows:
int x = -3000;
unsigned int mask = x >> 31;
int sign = mask & 0x01;
int positive = (x^mask) + sign;
printf("x:%d mask:%0X sign:%d positive:%d\n",x,mask,sign,positive);
Related
fitsBits - return 1 if x can be represented as an
n-bit, two's complement integer.
1 <= n <= 32
Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1
Legal ops: ! ~ & ^ | + << >>
My code is the following:
int fitsBits(int x, int n) {
int twos = ~x + 1; //two's complement
int ans;
ans = (twos >> (n);
ans = !ans;
return ans;
}
Working it on paper, it seems to work correctly but it fails when actually tested and I'm not sure why.
I'm assuming you are working on a 2s complement machine (vice sign-magnitude or some other kind of arithmetic) and need to avoid loops and conditionals as well. This is clearly some kind of puzzle, so let's not worry about portability and assume 32-bit ints.
If the value is positive, all bits from n-1 through the highest order bit of the int must be zeros. If the value is negative, the same bits must be ones. So one approach is to check those bits for the correct value.
This is equivalent to checking whether x >> (~0+n) is all zeros if x is positive and all ones otherwise. It "shifts out" the bits that are free to have any value.
We can also construct a mask that's all zeros if x is positive, else ones, with x >> 31.
Finally, we can check equality of any ints a and b using !(a ^ b).
Putting all this together, you'd get:
int fitBits(int val, int nbits) {
return !((val >> 31) ^ (val >> (~0 + nbits)));
}
You want the log base 2.
#include <stdio.h>
int fitsBits(unsigned int v, unsigned int n) {
unsigned int r = 0; // lg(v)
while (v >>= 1) {
r++;
}
if(r >= n) return 1;
return 0;
}
int main () {
printf(" 5,3 => %d\n", fitsBits( 5,3));
printf(" -4,3 => %d\n", fitsBits(-4,3));
}
output:
5,3 => 0
-4,3 => 1
This question I have tried to solve it but couldn't get any way. Any pointers would be appreciated.
Regular subtraction way of doing division is not the intention here, ingenious way of using shifting operator to get this done is the intention.
Although an answer has been accepted, I post mine for what it's worth.
UPDATE. This works by multiplying by a recurring binary fraction. In decimal 1/9 = 0.1111111 recurring. In binary, that is 1/1001 = 0.000111000111000111 recurring.
Notice the binary multiplier is in groups of 6 bits, decimal 7 recurring. So what I want to do here, is to multiply the dividend by 7, shift it right 6 bits, and add it to a running quotient. However to keep significance, I do the shift after the addition, and shift the quotient q after the loop ends to align it properly.
There are up to 6 iterations of the calculation loop for a 32 bit int (6 bits * 6 shifts = 36 bits).
#include<stdio.h>
int main(void)
{
unsigned x, y, q, d;
int i, err = 0;
for (x=1; x<100; x++) { // candidates
q = 0; // quotient
y = (x << 3) - x; // y = x * 7
while(y) { // until nothing significant
q += y; // add (effectively) binary 0.000111
y >>= 6; // realign
}
q >>= 6; // align
d = x / 9; // the true answer
if (d != q) {
printf ("%d / 9 = %d (%d)\n", x, q, d); // print any errors
err++;
}
}
printf ("Errors: %d\n", err);
return 0;
}
Unfortunately, this fails for every candidate that is a multiple of 9, for rounding error, due to the same reason that multiplying decimal 27 * 0.111111 = 2.999999 and not 3. So I now complicate the answer by keeping the 4 l.s. bits of the quotient for rounding. The result is it works for all int values limited by the two top nibbles, one for the * 7 and one for the * 16 significance.
#include<stdio.h>
int main(void)
{
unsigned x, y, q, d;
int i, err = 0;
for (x=1; x<0x00FFFFFF; x++) {
q = 8; // quotient with (effectively) 0.5 for rounding
y = (x << 3) - x; // y = x * 7
y <<= 4; // y *= 16 for rounding
while(y) { // until nothing significant
q += y; // add (effectively) binary 0.000111
y >>= 6; // realign
}
q >>= (4 + 6); // the 4 bits significance + recurrence
d = x / 9; // the true answer
if (d != q) {
printf ("%d / 9 = %d (%d)\n", x, q, d); // print any errors
err++;
}
}
printf ("Errors: %d\n", err);
return 0;
}
Here's a solution heavily inspired by Hacker's Delight that really uses only bit shifts:
def divu9(n):
q = n - (n >> 3)
q = q + (q >> 6)
q = q + (q>>12) + (q>>24); q = q >> 3
r = n - (((q << 2) << 1) + q)
return q + ((r + 7) >> 4)
#return q + (r > 8)
See this answer: https://stackoverflow.com/a/11694778/4907651
Exactly what you're looking for except the divisor is 3.
EDIT: explanation
I will replace the add function with simply + as you're looking for the solution without using * or / only.
In this explanation, we assume we are dividing by 3.
Also, I am assuming you know how to convert decimal to binary and vice versa.
int divideby3 (int num) {
int sum = 0;
while (num > 3) {
sum += (num >> 2);
num = (num >> 2) + (num & 3);
}
if (num == 3)
sum += 1;
return sum;
}
This approach uses bitwise operators:
bitwise AND: &.
bitwise left shift: <<. Shifts binary values left.
bitwise right shift: >>. Shifts binary values right.
bitwise XOR: ^
The first condition (num > 3) is as such because the divisor is 3. In your case, the divisor is 9, so when you use it, the condition must be (num > 9).
Suppose the number we want to divide is 6.
In binary, 6 is represented as 000110.
Now, we enter while (num > 3) loop. The first statement adds sum (initialised to 0) to num >> 2.
What num >> 2 does:
num in binary initially: 00000000 00000110
after bitwise shift: 00000000 00000001 i.e. 1 in decimal
sum after adding num >> 2 is 1.
Since we know num >> 2 is equal to 1, we add that to num & 3.
num in binary initially: 00000000 00000110
3 in binary: 00000000 00000011
For each bit position in the result of expression a & b, the bit is 1 if both operands contain 1, and 0 otherwise
result of num & 3: 00000000 00000010 i.e. 2 in decimal
num after num = (num >> 2) + (num & 3) equals 1 + 2 = 3
Now, since num is EQUAL to 3, we enter if (num==3) loop.
We then add 1 to sum, and return the value. This value of sum is the quotient.
As expected, the value returned is 2.
Hope that wasn't a horrible explanation.
Create a loop and every step you should substract N-9 .. then (N-9)-9 .. until N<9 OR N=0 and every substraction you count the step For exemple : 36/9 36-9=27 cmpt (1) 27-9=18 cmpt(2) 18-9=9 cmpt(3) 9-9=0 cmpt (4)
So 36/9= 4
This http://en.wikipedia.org/wiki/Ancient_Egyptian_multiplication algorithm can do it using only subtraction and binary shifts in log(n) time. However, as far as I know, state-of-the-art hardware already either use this one, or even better algorithms. Therefore, I do not think there is anything you can do (assuming performance is your goal) unless you can somehow avoid the division completely or change your use case so that you can divide by a power of 2, because there are some tricks for these cases.
If you're not allowed to multiply/divide, you're left with addition/subtraction. Dividing by a number shows how many times the divisor contains the dividend. You can use this in return: How many times can you subtract the number from the original value?
divisor = 85;
dividend = 9;
remaining = divisor;
result = 0;
while (remaining >= dividend)
{
remaining -= dividend;
result++;
}
std::cout << divisor << " / " << dividend << " = " << result;
If you need to divide a positive number, you can use the following function:
unsigned int divideBy9(unsigned int num)
{
unsigned int result = 0;
while (num >= 9)
{
result += 1;
num -= 9;
}
return result;
}
In the case of a negative number, you can use a similar approach.
Hope this helps!
// 1.5 Exercise 6.cpp : main project file.
#include "stdafx.h"
#include <stdio.h>
int sra(int x, int n);
int main()
{
int intInputNum;
int finalValue1;
int finalValue2;
printf("Please enter a integer and program will shift the integer 2 places to right,\n it will give value for both arithmetic as well as Logical shift\n");
scanf("%d",&intInputNum);
finalValue1 = intInputNum >> 2;
finalValue2 = sra(intInputNum, 2);
printf("Logical %d \n Arithmetic %d\n", finalValue1, finalValue2);
return 0;
}
int sra(int x, int k)
{
int xsrl = (unsigned)x >> k;
unsigned mask = k ? ((1 << (8 * sizeof(int)-k)) - 1) : 0;
return (x < 0) ? mask | xsrl : xsrl;
}
Sample run:
Please enter a integer and program will shift the integer 2 places to right,
it will give value for both arithmetic as well as Logical shift
-500
Logical -125
Arithmetic 1073741823
Why is this not showing the correct value?
The standard doesn't guarantee anything (i.e. it's either Undefined Behaviour in the << case or Implementation Defined in (your) >> case) for shift operations on negative left-hand-side (LHS) arguments.
unsigned mask = k ? ((1 << (8 * sizeof(int)-k)) - 1) : 0;
I think this cannot be what you wanted.
Example (k==1):
mask = 0x7FFFFFFF
Then you use "mask | xsrl" which gives "0x7FFFFFFF" (it's an OR operation...)
Just thinking aloud: I think you might want
unsigned mask = k ? (0xFFFFFFFF<<(32-k)) : 0;
To be really precise:
unsigned int mask = 0;
if ( k > 0 && k <= (8*sizeof(int)))
mask = UINT_MAX<<((8*sizeof(int))-k);
and you need to include "limits.h" to get "UINT_MAX".
Now, here is the function header of the function I'm supposed to implement:
/*
* float_from_int - Return bit-level equivalent of expression (float) x
* Result is returned as unsigned int, but
* it is to be interpreted as the bit-level representation of a
* single-precision floating point values.
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
* Max ops: 30
* Rating: 4
*/
unsigned float_from_int(int x) {
...
}
We aren't allowed to do float operations, or any kind of casting.
Now I tried to implement the first algorithm given at this site: http://locklessinc.com/articles/i2f/
Here's my code:
unsigned float_from_int(int x) {
// grab sign bit
int xIsNegative = 0;
int absValOfX = x;
if(x < 0){
xIsNegative = 1;
absValOfX = -x;
}
// zero case
if(x == 0){
return 0;
}
if(x == 0x80000000){ //Updated to add this
return 0xcf000000;
}
//int shiftsNeeded = 0;
/*while(){
shiftsNeeded++;
}*/
unsigned I2F_MAX_BITS = 15;
unsigned I2F_MAX_INPUT = ((1 << I2F_MAX_BITS) - 1);
unsigned I2F_SHIFT = (24 - I2F_MAX_BITS);
unsigned result, i, exponent, fraction;
if ((absValOfX & I2F_MAX_INPUT) == 0)
result = 0;
else {
exponent = 126 + I2F_MAX_BITS;
fraction = (absValOfX & I2F_MAX_INPUT) << I2F_SHIFT;
i = 0;
while(i < I2F_MAX_BITS) {
if (fraction & 0x800000)
break;
else {
fraction = fraction << 1;
exponent = exponent - 1;
}
i++;
}
result = (xIsNegative << 31) | exponent << 23 | (fraction & 0x7fffff);
}
return result;
}
But it didn't work (see test error below):
ERROR: Test float_from_int(8388608[0x800000]) failed...
...Gives 0[0x0]. Should be 1258291200[0x4b000000]
I don't know where to go from here. How should I go about parsing the float from this int?
EDIT #1:
You might be able to see from my code that I also started working on this algorithm (see this site):
I assumed 10-bit, 2’s complement, integers since the mantissa is only
9 bits, but the process generalizes to more bits.
Save the sign bit of the input and take the absolute value of the input.
Shift the input left until the high order bit is set and count the number of shifts required. This forms the floating mantissa.
Form the floating exponent by subtracting the number of shifts from step 2 from the constant 137 or (0h89-(#of shifts)).
Assemble the float from the sign, mantissa, and exponent.
But, that doesn't seem right. How could I convert 0x80000000? Doesn't make sense.
EDIT #2:
I think it's because I say max bits is 15... hmmm...
EDIT #3: Screw that old algorithm, I'm starting over:
unsigned float_from_int(int x) {
// grab sign bit
int xIsNegative = 0;
int absValOfX = x;
if(x < 0){
xIsNegative = 1;
absValOfX = -x;
}
// zero case
if(x == 0){
return 0;
}
if (x == 0x80000000){
return 0xcf000000;
}
int shiftsNeeded = 0;
int counter = 0;
while(((absValOfX >> counter) & 1) != 1 && shiftsNeeded < 32){
counter++;
shiftsNeeded++;
}
unsigned exponent = shiftsNeeded + 127;
unsigned result = (xIsNegative << 31) | (exponent << 23);
return result;
Here's the error I get on this one (I think I got past the last error):
ERROR: Test float_from_int(-2139095040[0x80800000]) failed...
...Gives -889192448[0xcb000000]. Should be -822149120[0xceff0000]
May be helpful to know that:
absValOfX = 7f800000
(using printf)
EDIT #4: Ah, I'm finding the exponent wrong, need to count from the left, then subtract from 32 I believe.
EDIT #5: I started over, now trying to deal with weird rounding problems...
if (x == 0){
return 0; // 0 is a special case because it has no 1 bits
}
if (x >= 0x80000000 && x <= 0x80000040){
return 0xcf000000;
}
// Save the sign bit of the input and take the absolute value of the input.
unsigned signBit = 0;
unsigned absX = (unsigned)x;
if (x < 0)
{
signBit = 0x80000000u;
absX = (unsigned)-x;
}
// Shift the input left until the high order bit is set to form the mantissa.
// Form the floating exponent by subtracting the number of shifts from 158.
unsigned exponent = 158;
while ((absX & 0x80000000) == 0)
{
exponent--;
absX <<= 1;
}
unsigned negativeRoundUp = (absX >> 7) & 1 & (absX >> 8);
// compute mantissa
unsigned mantissa = (absX >> 8) + ((negativeRoundUp) || (!signBit & (absX >> 7) & (exponent < 156)));
printf("absX = %x, absX >> 8 = %x, exponent = %i, mantissa = %x\n", absX, (absX >> 8), exponent, mantissa);
// Assemble the float from the sign, mantissa, and exponent.
return signBit | ((exponent << 23) + (signBit & negativeRoundUp)) | ( (mantissa) & 0x7fffff);
-
absX = fe000084, absX >> 8 = fe0000, exponent = 156, mantissa = fe0000
ERROR: Test float_from_int(1065353249[0x3f800021]) failed...
...Gives 1316880384[0x4e7e0000]. Should be 1316880385[0x4e7e0001]
EDIT #6
Did it again, still, the rounding doesn't work properly. I've tried to hack together some rounding, but it just won't work...
unsigned float_from_int(int x) {
/*
If N is negative, negate it in two's complement. Set the high bit (2^31) of the result.
If N < 2^23, left shift it (multiply by 2) until it is greater or equal to.
If N ≥ 2^24, right shift it (unsigned divide by 2) until it is less.
Bitwise AND with ~2^23 (one's complement).
If it was less, subtract the number of left shifts from 150 (127+23).
If it was more, add the number of right shifts to 150.
This new number is the exponent. Left shift it by 23 and add it to the number from step 3.
*/
printf("---------------\n");
//printf("x = %i (%x), -x = %i, (%x)\n", x, x, -x, -x);
if(x == 0){
return 0;
}
if(x == 0x80000000){
return 0xcf000000;
}
// If N is negative, negate it in two's complement. Set the high bit of the result
unsigned signBit = 0;
if (x < 0){
signBit = 0x80000000;
x = -x;
}
printf("abs val of x = %i (%x)\n", x, x);
int roundTowardsZero = 0;
int lastDigitLeaving = 0;
int shiftAmount = 0;
int originalAbsX = x;
// If N < 2^23, left shift it (multiply it by 2) until it is great or equal to.
if(x < (8388608)){
while(x < (8388608)){
//printf(" minus shift and x = %i", x );
x = x << 1;
shiftAmount--;
}
} // If N >= 2^24, right shfit it (unsigned divide by 2) until it is less.
else if(x >= (16777215)){
while(x >= (16777215)){
/*if(x & 1){
roundTowardsZero = 1;
printf("zzz Got here ---");
}*/
lastDigitLeaving = (x >> 1) & 1;
//printf(" plus shift and x = %i", x);
x = x >> 1;
shiftAmount++;
}
//Round towards zero
x = (x + (lastDigitLeaving && (!(originalAbsX > 16777216) || signBit)));
printf("x = %i\n", x);
//shiftAmount = shiftAmount + roundTowardsZero;
}
printf("roundTowardsZero = %i, shiftAmount = %i (%x)\n", roundTowardsZero, shiftAmount, shiftAmount);
// Bitwise AND with 0x7fffff
x = x & 0x7fffff;
unsigned exponent = 150 + shiftAmount;
unsigned rightPlaceExponent = exponent << 23;
printf("exponent = %i, rightPlaceExponent = %x\n", exponent, rightPlaceExponent);
unsigned result = signBit | rightPlaceExponent | x;
return result;
The problem is that the lowest int is -2147483648, but the highest is 2147483647, so there is no absolute value of -2147483648. While you could work around it, I would just make a special case for that one bit pattern (like you do for 0):
if (x == 0)
return 0;
if (x == -2147483648)
return 0xcf000000;
The other problem is that you copied an algorithm that only works for numbers from 0 to 32767. Further down in the article they explain how to expand it to all ints, but it uses operations that you're likely not allowed to use.
I would recommend writing it from scratch based on the algorithm mentioned in your edit. Here's a version in C# that rounds towards 0:
uint float_from_int(int x)
{
if (x == 0)
return 0; // 0 is a special case because it has no 1 bits
// Save the sign bit of the input and take the absolute value of the input.
uint signBit = 0;
uint absX = (uint)x;
if (x < 0)
{
signBit = 0x80000000u;
absX = (uint)-x;
}
// Shift the input left until the high order bit is set to form the mantissa.
// Form the floating exponent by subtracting the number of shifts from 158.
uint exponent = 158;
while ((absX & 0x80000000) == 0)
{
exponent--;
absX <<= 1;
}
// compute mantissa
uint mantissa = absX >> 8;
// Assemble the float from the sign, mantissa, and exponent.
return signBit | (exponent << 23) | (mantissa & 0x7fffff);
}
The basic formulation of the algorithm is to determine the sign, exponent and mantissa bits, then pack the result into an integer. Breaking it down this way makes it easy to clearly separate the tasks in code and makes solving the problem (and testing your algorithm) much easier.
The sign bit is the easiest, and getting rid of it makes finding the exponent easier. You can distinguish four cases: 0, 0x80000000, [-0x7ffffff, -1], and [1, 0x7fffffff]. The first two are special cases, and you can trivially get the sign bit in the last two cases (and the absolute value of the input). If you're going to cast to unsigned, you can get away with not special-casing 0x80000000 as I mentioned in a comment.
Next up, find the exponent -- there's an easy (and costly) looping way, and a trickier but faster way to do this. My absolute favourite page for this is Sean Anderson's bit hacks page. One of the algorithms shows a very quick loop-less way to find the log2 of an integer in only seven operations.
Once you know the exponent, then finding the mantissa is easy. You just drop the leading one bit, then shift the result either left or right depending on the exponent's value.
If you use the fast log2 algorithm, you can probably end up with an algorithm which uses no more than 20 operations.
Dealing with 0x80000000 is pretty easy:
int xIsNegative = 0;
unsigned int absValOfX = x;
if (x < 0)
{
xIsNegative = 1;
absValOfX = -(unsigned int)x;
}
It gets rid of special casing -2147483648 since that value is representable as an unsigned value, and absValOfX should always be positive.
I have a number that is "significant byte", it may be 0 or 255.
Which means 0 or -1.
How to convert 255 to -1 in one time.
I have a function that doesn't works for me:
acc->x = ((raw_data[1]) << 8) | raw_data[0];
Assuming that every 8th bit set to 1 means negative (254 == -2) then a widening conversion from signed types should do:
int n = (signed char)somebyte;
so
unsigned char rawdate[2] = ...;
int msbyte = (signed char)rawdata[1];
acc->x = (msbyte << 8) | (raw_data[0] & 0xFF);
I am not sure what is required but here are the rules for arithmetic conversions of integers.
If an integer is assigned to another lower bit integer, the data will be truncated.
Example:
struct A {
int c1 : 8;
unsigned c2 : 8;
} a;
int main()
{
short int i = 255; // right 8 bits containing all bits set
a.c1 = i; // or a.c1 = 255. casting not required.
a.c2 = i; // same as above.
// prints -1, 255
printf("c1: %d c2: %d\n", a.c1, a.c2);
i = 511; // 9 number of 1 bits
a.c1 = i; // left 9th bit will be truncated. casting not required.
a.c2 = i; // same as above
// prints -1, 255
printf("c1: %d c2: %d\n", a.c1, a.c2);
return 0;
}
If a signed 8 bit integer (or char) is assigned to higher bit integer (say int), it's sign bit will be shifted.
ex:
char c = 255; // which is -1
int i = c; // i is now -1. sign bit will be shifted to 32nd bit.