Lefteris
Lefteris

Reputation:

Implementing floating point subtraction

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;

}

Upvotes: 4

Views: 4451

Answers (2)

David Thornley
David Thornley

Reputation: 57066

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.

Upvotes: 1

MSalters
MSalters

Reputation: 180225

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

Upvotes: 1

Related Questions