Multiplying negatives using bitwise minipulation

Pages: 12
im making a function that uses bitwise operands to multiply a number by two, i got that for positives you just << by 1 but how would you do it for negatives?
It also works with negative values.
unsigned float_twice(unsigned uf) {
if((uf << 1) == 0)
return uf;
return uf<<1;
}
this is the function the:
if((uf << 1) == 0) accounts for overflow


ERROR: Test float_twice(-2139095040[0x80800000]) failed...
...Gives 16777216[0x1000000]. Should be -2130706432[0x81000000]

this is the most recent error given by the test program
Last edited on
Ah, well, yes. It only works as expected if the left operand is signed. Unsigned values are always positive, after all.
Last edited on
anyhelp on how to do it unsigned?
Cast the operand to signed.
it is for a project and must remain unsigned
I'm not telling you to change the signature of the function. Just cast the value inside the function. Otherwise, what you're doing doesn't make sense because you want positive values to behave as negative values. It's like expecting that 2+1=1.
changed the function to:

1
2
3
4
5
6
7
8
unsigned float_twice(unsigned uf) {

 signed sf=uf;
 if((sf<<1) == 0)
        return uf;
 sf=sf << 1;
 uf = sf;
 return uf;


and it still returns the error:
ERROR: Test float_twice(-2139095040[0x80800000]) failed...
...Gives 16777216[0x1000000]. Should be -2130706432[0x81000000]

Huh. Never mind, I got confused. The opposite was true. Shifting to the right copies the sign to lower bits.

You'll just have to check if the parameter is negative and if it is, invert its sign, shift, then invert again.
1
2
3
4
5
6
7
8
9
10
11
12
13
unsigned float_twice(unsigned uf) {
 if((uf << 1) == 0)
        return uf;
 else if(uf < 0){
        uf = uf & 2147483647;
        uf = uf << 1;
        uf = uf & 2147483647;
        return uf;
 }
 else
 return uf<<1;
}
 

here is what we have now but we still get the same error as before
Last edited on
uf = uf & 255;
This doesn't invert any sign. You're just changing the value you were given for no good reason.

uf < 0
You're still making the same mistake. An unsigned value is always positive.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
unsigned float_twice(unsigned uf) {
 signed float sf=uf;
 if((sf << 1) == 0)
        return uf;
 else if(sf < 0){
        sf = sf & 2147483647;
        sf = sf << 1;
        sf = sf & 2147483647;
        uf=sf;
        return uf;
 }
 else
 return uf<<1;
}


we realized both problems just before you posted that and changed the function to this again same error
Why float this time? You're working with integers, are you not?

1
2
3
4
5
6
7
8
9
10
11
12
unsigned float_twice(unsigned uf) {
    signed sf=uf;
    if (sf < 0){
        sf=-sf;
        if ((sf<<=1) == 0)
            return uf;
        return -sf;
    }
    if ((uf<<1) == 0)
        return uf;
    return uf<<1;
}
Last edited on
i tried your solution that you posted and came up with the same error message.



i changed your code a bit
1
2
 if ((sf<<1) == 0)
			return uf;



and got the following error message instead of the one i was getting.

ERROR: Test float_twice(-2139095040[0x80800000]) failed...
...Gives -2139095040[0x80800000]. Should be -2130706432[0x81000000]
Last edited on
Well, if you change the code, then it's not really my code anymore, is it? Why don't you try it exactly as I posted it?
i did try your solution and it was returning the original error after i applied the listed fix it gave us the new error message
Gah! I'm so stupid. Now I see it. The test vector is not using two's complement at all!

To check if the number is negative, bitwise-AND with 0x80000000.
To invert the sign, bitwise-XOR with 0x80000000.
Don't use signed types anywhere.
Leave the rest unchanged.

EDIT: I changed the first of the values. Also note that this representation may have two zeroes: 0 and 0x80000000.
Last edited on
else if((uf & 0x8000000) > 0){
i know this is very very wrong but i cannot think how i am supposed to use the bitwise and to check if it is negative or not without using signs
Last edited on
ANDing by that value will clear all bits 0-30, so if the result is non-zero, bit 31 is set. if (uf&0x80000000) is enough.

And I keep making the same stupid mistake of hitting the zero key six times. Those are supposed to be 0x80000000.

EDIT: In general, you can do this:
#define CHECK_FLAG(x,pattern) (((x)&(pattern))==(pattern))
Last edited on
Pages: 12