简体   繁体   English

C语言中的浮点加法

[英]Floating Point Addition in C

I'm having trouble with Floating Point Addition in C. 我在C语言中使用浮点加法时遇到麻烦。

We're given two 16 bit numbers, we're supposed to add them not worrying about cases where their signs are different or where the exponents are 0 or 31. 我们给了两个16位数字,我们应该添加它们而不用担心它们的符号不同或指数为0或31的情况。
This is a homework assignment, but I'm late & I can't figure out why it's not working. 这是一项家庭作业,但是我迟到了,我不知道为什么它不起作用。

The Algrothim sort of looks like: Algrothim的外观如下:

  1. Get the sign bits of each number, if their different return 0. 如果每个数字的符号位不同,则返回0。
  2. Get the exponents of each number, find the bigger one 2a. 获取每个数字的指数,找到较大的2a。 find out the difference between the two. 找出两者之间的区别。
  3. in the 11th bit put in a implicit one into each of the mantissa's 在第11位中,每个尾数中都隐含一个
  4. Right shift the number with the smaller exponent by the difference of the exponents 将指数较小的数字右移指数的差
  5. Take the sign and exponent of the larger number or it with the shifted mantissa. 取较大数字的符号和指数,或将其与移位的尾数相乘。
  6. Return the result. 返回结果。

Here's my code: 这是我的代码:

LC3_Word FLADD(LC3_Word A, LC3_Word B)
{
    // a debug variable, so we can turn errors on (debug = 1) and off (debug = 0)
    int debug = 1; 

    // a default return value 
    LC3_Word returnValue = 0x0000;

    if(debug)
    {
        printf("-----------------------------------\nBegin debug\n-----------------------------------\n");
        printf("Return value: %x \n",returnValue); 
        printf("LC3 words: A %x, B %x\n",A,B);
    }

    // Masks to extract sign, exponent and fraction 
    LC3_Word signBitMask = 0x8000; 
    LC3_Word expMask = 0x7C000; 
    LC3_Word mantissaMask = 0x03FF; 

    // Mask to get the sign with the exponent
    LC3_Word signExpMask = 0xFC00;

    // A mask for the implicit 1
    LC3_Word implicitOne = 0x0400; 

    // Getting the signs
    LC3_Word signA = AND(signBitMask,A); 
    LC3_Word signB = AND(signBitMask,B);

    // Getting the exponents 
    LC3_Word expA = AND(expMask,A); 
    LC3_Word expB = AND(expMask,B); 

    // Getting the mantissa's 
    LC3_Word mantA = AND(mantissaMask,A);
    LC3_Word mantB = AND(mantissaMask,B);

        if(debug)
        {
            printf("======================\n");
            printf("\tSignBitMask: %x\n\texpMask: %x\n\tmantissaMask: %x\n",signBitMask,expMask,mantissaMask);
            printf("\tSign EXP Mask: %x\n",signExpMask);
            printf("\tsignA: %x, signB: %x\n", signA, signB); 
            printf("\tImplicit One Mask: %x\n",implicitOne); 
            printf("\tExp of a: %x, Exp of b: %x\n", expA, expB); 
            printf("\tmantissa of A: %x,mantissa of B: %x\n",mantA,mantB);
            printf("======================\n");
        }

    // Getting each with it's sign bit and it's exponent 
    LC3_Word signExpA = AND(signExpMask,A); 
    LC3_Word signExpB = AND(signExpMask,B); 

        if(debug)
        {
            printf("signExpA of A: %i, signExpB of B: %i\n",signExpA,signExpB);
        }

    // if the signs are different, don't deal with this case 
    if(signA!=signB)
    {
        return 0; 
    }   

    // if the signs are the same, if not, just return the default value 
    if(signA==signB)
    {
        if(debug)
        {
            printf("We got into the if signs are the same block \n");
            printf("Sign a: %i, Sign b: %i \n",signA,signB); 
        }

        if(expA==expB)
        {
            if(debug)
            {
                printf("We got into the if exponents are the same block \n");
                printf("Exp a: %x, Exp b: %x \n",expA,expB); 
            }

            // exponents are the same
            // Add Mantissa B to A 
            mantA = ADD(mantB,mantA);
            if(debug)
            {
                printf("Addition of mantissa's %x\n",mantA); 
            }
            // store into the return value the logical and of the mantissa with the existing exponent and sign
            // might want to do an OR() not an AND()
            returnValue = OR(signExpA,mantA); 
        } // end if the eponents are the same 
        else {
            if(debug)
            {
                printf("The exponents are not the same block \n");
            }
            // Getting the size we need to shift by
            int sizeToShift = 0; 
            if(expA>expB)
            {
                // Mask the mantissa of B with a implicit 1, then right shift
                mantB = OR(implicitOne,mantB); 

                if(debug)
                {
                    printf("The exponent a is > b\n");
                }
                // need to shift B, getting the size of how much
                sizeToShift = expA-expB;

                if(debug)
                {
                    printf("size to shift: %d,\nmantissaB is: %x\n",sizeToShift,mantB); 
                }
                // right shifting the mantissa of b
                mantB = mantB >> sizeToShift; 

                if(debug)
                {
                    printf("mantissa of b shifted: %x\n",mantB);
                }
                returnValue = OR(signExpA,ADD(mantA,mantB));
            }// end if A > B in the exponent 
            else
            {
                // Mask the mantissa of A with a implicit 1, then right shift
                mantA = OR(implicitOne,mantA);
                if(debug)
                {
                    printf("The exponent B is > A\n");
                }
                // need to shift A, getting the size of how much
                sizeToShift = expB-expA;

                if(debug)
                {
                    printf("size to shift: %d,\nmantissaA is: %x\n",sizeToShift,mantA); 
                }
                // right shifting the mantissa of A
                mantA = mantA >> sizeToShift; 

                if(debug)
                {
                    printf("mantissa of A shifted: %x\n",mantA);
                }
                returnValue = OR(signExpB,ADD(mantA,mantB));
            }// end if B > A in the exponent        
        }// end if different exponents 
    } // end if the signs are the same

    if(debug)
    {
        printf("Return Value %x\n",returnValue);
        printf("-----------------------------------\nEnd debug\n-----------------------------------\n");
    }

    return returnValue;
}

Here are ADD, OR and AND, 这是ADD,OR和AND,

LC3_Word AND(LC3_Word A, LC3_Word B)
{
    return (A&B);
}

LC3_Word OR(LC3_Word A, LC3_Word B)
{
    return (A|B);
}

LC3_Word ADD(LC3_Word A, LC3_Word B)
{
    return (A+B); 
}

When I add 2 + 3 in floating point I get 3 instead of 5. 当我在浮点数中加上2 + 3时,我得到3而不是5。

Any ideas? 有任何想法吗?

    if(expA==expB)
    {
        if(debug)
        {
            printf("We got into the if exponents are the same block \n");
            printf("Exp a: %x, Exp b: %x \n",expA,expB); 
        }

        // exponents are the same
        // Add Mantissa B to A 
        mantA = ADD(mantB,mantA);
        if(debug)
        {
            printf("Addition of mantissa's %x\n",mantA); 
        }
        // store into the return value the logical and of the mantissa with the existing exponent and sign
        // might want to do an OR() not an AND()
        returnValue = OR(signExpA,mantA); 
    } // end if the eponents are the same 

This is wrong. 错了

You're failing to account for the addition of the two implicit ones. 您没有考虑到两个隐式加法的相加。 When you're adding 2 + 3 you're adding 1.0 x 2^1 + 1.1 x 2^1 and you're ignoring everything before the decimal point... So you end up with 0.0 + 0.1 = 0.1 and just stick a 1 at the front. 当您添加2 + 3时,您添加的是1.0 x 2 ^ 1 + 1.1 x 2 ^ 1,而忽略了小数点前的所有内容...因此最终得到0.0 + 0.1 = 0.1并坚持1在前面。 You need to add the two implicit ones as well. 您还需要添加两个隐式的。

Try something like this: 尝试这样的事情:

    if(expA==expB)
    {
        if(debug)
        {
            printf("We got into the if exponents are the same block \n");
            printf("Exp a: %x, Exp b: %x \n",expA,expB); 
        }

        // exponents are the same
        // Add Mantissa B to A 
        mantA = OR(implicitOne,mantA);
        mantB = OR(implicitOne,mantB);

        mantA = ADD(mantB,mantA);

        // You need to normalize this now. But shifting to the right by 1 will suffice.
        mantA >>= 1;
        ++expA;
        // ... add the sign and you're done...

        if(debug)
        {
            printf("Addition of mantissa's %x\n",mantA); 
        }
        // store into the return value the logical and of the mantissa with the existing exponent and sign
        // might want to do an OR() not an AND()
        returnValue = OR(signExpA,mantA); 
    } // end if the eponents are the same 

I'm still reading through the code but shouldn't 我仍在阅读代码,但不应

LC3_Word expMask = 0x7C000; LC3_Word expMask = 0x7C000;

be

LC3_Word expMask = 0x7C00;? LC3_Word expMask = 0x7C00 ;?

Also, can you paste binary representations of your numbers? 另外,您可以粘贴数字的二进制表示形式吗? Just so we are clear on what is being put through this algorithm. 这样我们就很清楚此算法要处理的内容。 The bug could also be in your conversion code if you are using one... 如果您使用的是此错误,也可能在转换代码中...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM