views:

718

answers:

2

Hello , all I am trying to implement a floating point arithmetic library and I have trouble understanding the algorithm of subtracting floats. I have implemented addition succesfully and I thought that subtraction was just a special case of it but it seems I am making a mistake somewhere. I am adding the code here just for reference, it has many self explanatory functions but I don't expect someone to understand it 100%. What I would like help with is the algorithm. We follow the same method as with adding float numbers except, when we add the mantissas, we convert the negative one(the one we subtract) into two's complement and then add them?

That's what I am doing but the result is not correct. Albeit it is very close ... but not the same. Anyone has any ideas? Thanks in advance!

I am quite sure that the way I do things works since I implemented an almost identical algorithm for adding floats and it works like a charm.

_float subFloat(_float f1,_float f2)
{
unsigned char diff;
_float result;

//first see whose exponent is greater
if(f1.float_parts.exponent > f2.float_parts.exponent)
{
    diff = f1.float_parts.exponent - f2.float_parts.exponent;

    //now shift f2's mantissa by the difference of their exponent to the right
    //adding the hidden bit
    f2.float_parts.mantissa = ((f2.float_parts.mantissa)>>1) | (0x01<<22);
    f2.float_parts.mantissa >>= (int)(diff);//was (diff-1)

    //also increase its exponent by the difference shifted
    f2.float_parts.exponent = f2.float_parts.exponent + diff;
}
else if(f1.float_parts.exponent < f2.float_parts.exponent)
{
    diff = f2.float_parts.exponent - f1.float_parts.exponent;
    result = f1;
    f1 = f2;        //swap them
    f2 = result;

    //now shift f2's mantissa by the difference of their exponent to the right
    //adding the hidden bit
    f2.float_parts.mantissa = ((f2.float_parts.mantissa)>>1) | (0x01<<22);
    f2.float_parts.mantissa >>= (int)(diff);

    //also increase its exponent by the difference shifted
    f2.float_parts.exponent = f2.float_parts.exponent + diff;
}
else//if the exponents were equal
  f2.float_parts.mantissa = ((f2.float_parts.mantissa)>>1) | (0x01<<22); //bring out the hidden bit




//getting two's complement of f2 mantissa
f2.float_parts.mantissa ^= 0x7FFFFF;
f2.float_parts.mantissa += 0x01;



result.float_parts.exponent = f1.float_parts.exponent;
result.float_parts.mantissa = (f1.float_parts.mantissa +f2.float_parts.mantissa)>>1;
                                                //gotta shift right by overflow bits

//normalization
if(manBitSet(result,1))
    result.float_parts.mantissa <<= 1;  //hide the hidden bit
else
    result.float_parts.exponent +=1;

return result;

}
+1  A: 

a-b == a+(-b), and unary minus is trivial, so I wouldn't even bother with binary minus.

MSalters
Thank you for you answer but I do not understand what you mean.
4 - 2 == 4 + (-2). Just flip the sign bit.
Hans Passant
MSalters is suggesting that you perform subtraction by negating one of the addends and then adding as normal. Judging by your line in your original post that "subtraction is just a special case", I think you already knew that...
rmeador
No I think you misunderstood. I can't just change the sign bit and add. When I said that my addition works I meant that addition of same sign floats works. Subtraction is adding different signed floats. That's what the above code is for, but it does not give the expected result.
A: 

If your addition code is correct, and your subtraction isn't, the problem is presumably in the two's complement and addition.

Is it necessary to do the two's complement and addition, rather than subtraction?

If that's not the problem, I'm having trouble with your algorithm. It's been a while since I did anything like this. Could you provide some details? More specifically, what is the hidden bit?

It seems possible to me that the handling of the hidden bit is proper for addition but not subtraction. Could it be that you should set it in the f1 mantissa rather than the f2? Or negate the f1 mantissa instead of the f2?

Without knowing what you're getting versus what you're expecting, and more details of the algorithm you're using, that's the best I can do.

Edit: OK, I looked at the references in your comment. One thing you are failing to do in the supplied code is normalization. When adding, either the hidden bits overflow (shift mantissa to the left, increment exponent), or they don't. When subtracting, arbitrary parts of the mantissa can be zero. In decimal, consider adding 0.5E1 and 0.50001E1; you'd get 1.00001E1 and if you were to normalize you'd get 0.10001E2. When subtracting the 0.5E1 from 0.50001E1, you get 0.00001E1. Then you need to shift the mantissa to the left and decrement the exponent by as much as it takes, to get 0.1E-4.

David Thornley
Thanks for your reply, well the algorithm is the usual way of subtracting floats. Check these for example:http://www.cs.uaf.edu/~cs301/notes/Chapter6/node3.html#SECTION00120000000000000000and/or here :http://pages.cs.wisc.edu/~smoler/x86text/lect.notes/arith.flpt.html
Yeah I was tottally of as far as normalization was concerned in this. I corrected it and also implemented correctly (it seems) multiplication and division. Got them all now :) , thanks a lot for your help.