# Floating point arithmetic - unexpected results in certain test cases

I was hoping I could get some help with a floating point adder I'm designing in verilog. The test case I am having trouble with is adding the following 2 numbers:

                  -    37       1.96533143520
Op A: 0x92fb8ffb (1 00100101 11110111000111111111011)
+    36       1.08916580677
Op B: 0x120b69c9 (0 00100100 00010110110100111001001)


The difference in exponents is 1. So I add the hidden bit back in to both mantissas, shift mantissa B to the right by 1 and add. I do not round because the remainder is exactly half and the LSB of the Mant is 0 (I'm using round to even).

Mant A: 0xfb8ffb (111110111000111111111011)
Mant B: 0x45b4e4 (010001011011010011100100.1) G=1, R=0, S=0
Sum:    0xb5db17 (101101011101101100010111)


The sum is already normalized so I do not do any further modification to the mantissa. I use the sign and exponent of Operand A and the new mantissa sum to provide the result, but I do not get the expected result:

                      -    37          1.4207485914
Result:   0x92b5db17 (1 00100101 01101011101101100010111)
-    37          1.4207484722
Expected: 0x92b5db16 (1 00100101 01101011101101100010110


Is there someone who can help me understand what is going on? Is the issue that I am supposed to wait until AFTER adding the mantissas to determine whether to round or not? I don't see why this would make a difference.

• @jcaron Differ from what? There is still only one right result, I think? Commented Feb 23, 2023 at 23:00
• @user253751 Differ between the result computed directly in decimal and the result computed by converting to binary, making the addition, and converting back to decimal. I thought that was what OP was trying to compare (I was on mobile and did not make the actual computation), but that doesn't seem to be the case. Commented Feb 24, 2023 at 0:15
• I believe the issue is that the addition (subtraction, really) should be made with additional bits (to the right), and then rounded. It would result in ...1011.000 - ...0100.100 = ...0110.100 = ...0110 (round to even). Wikipedia says "the rounded result is as if infinitely precise arithmetic was used to compute the value and then rounded (although in implementation only three extra bits are needed to ensure this)" Commented Feb 24, 2023 at 0:16
• @jcaron Why do you think the expected result was computed in decimal? Commented Feb 24, 2023 at 0:26
• @user253751 That's what I initially thought, but as I wrote above, clearly isn't the case. I removed my comment. Commented Feb 24, 2023 at 0:29

## 1 Answer

It's probably not necessary to say to you, but you are adding very small numbers together. For those who don't know much about IEEE-754, 32-bit FP uses an excess-127 notation for the exponent. So in your cases, the exponents are -90 and -91. Which makes for very small (but not denormal) values.

With the hidden bit restored, you have:

1.11110111000111111111011 (-) * 2^(-90) [37]
1.00010110110100111001001 (+) * 2^(-91) [36]


The mantissa is always taken as unsigned. And since the signs are different you should subtract the smaller from the larger (and retain the sign of the larger.) You don't add them. (I don't know where you got that idea of adding them.)

You need to align the exponents (they need to be the same.) This either means shifting the mantissa of the larger magnitude one to the left (or moving its radix point to the right) until the exponents match or else shifting the mantissa of the smaller magnitude one to the right (or moving its radix point to the left) again until the exponents match. Given my interpretation of what you wrote, you are shifting the smaller to the right. That's fine. But you will need one guard bit -- meaning that you work with the 23-bit mantissa, plus the hidden bit, plus a guard bit, making it a 25-bit subtraction process.

                         ,--- guard bit
|
v
1.111101110001111111110110 (-) * 2^(-90) [37]
0.100010110110100111001001 (+) * 2^(-90) [37]
--------------------------
1.011010111011011000101101 (-) * 2^(-90) [37]

1011010111011011000101101  (-) * 2^(-90) [37]  <-- normalized, no radix

011010111011011000101101  (-) * 2^(-90) [37]  <-- hidden bit removed

01101011101101100010110   (-) * 2^(-90) [37]  <-- guard bit dropped

1 00100101 01101011101101100010110    <-- prefix sign & exponent to mantissa

1001 0010 1011 0101 1101 1011 0001 0110
9    2    B    5    D    B    1    6


So the result is 92B5DB16. Isn't that what you wanted?

• I apologize for my wording, but I was subtracting. I was considering it the "sum of a negative number" but in actuality if you look at the mantissas I'm subtracting mantissa b from mantissa a Commented Feb 25, 2023 at 1:07
• In your calculation, you are calling the LSB on mantissa A the guard bit. I have been calling the LSB of shifted mantissa B the guard bit, because mantissa B is the one being shifted. I've seen different interpretations of the guard bit, where some consider it the MSB of what's shifted out of the mantissa, and some consider it the LSB left in the mantissa after it's been shifted. Commented Feb 25, 2023 at 1:13
• Thanks for your help. The way I was doing it was a 24-bit subtraction, with the 1 that gets shifted out of mantissa B being considered the guard bit. Because that value is exactly half, I was not rounding. But it seems this may not be the correct way to do this calculation Commented Feb 25, 2023 at 1:20
• @NoahWecoso In this particular case, which is unusual and not normal, it just turned out that the LSB went into the guard bit. But in other cases, the LSB will be nowhere to be seen, as it gets shifted still further away and disappears. Commented Feb 25, 2023 at 1:27