0

我被分配了使用有符号乘数执行无符号乘法的任务。尽管多次尝试,我无法得到它。是否有可能做到这一点?

代码:

#include <stdio.h>
int main()
{
    // Must be short int
    short int a=0x7fff;
    short int b=0xc000;
    unsigned int res1;
    signed int res2;
    
    //unsigned multiplier
    res1= (unsigned short int) a * (unsigned short int) b;
    
    //signed multiplier
    res2= (short int) a * (short int) b;

    printf("res1: 0x%x %d \n res2: 0x%x %d\n",res1,res1,res2,res2);
    return 0;
}

这是提供的代码。

电流输出:

res1: 0x5fff4000 1610563584 
res2: 0xe0004000 -536854528

预期输出:

res1: 0x5fff4000 1610563584 
res2: 0x5fff4000 1610563584 

工作代码:

#include<stdio.h>
#include<conio.h>
int main()
{
    short int a = 0x7fff;
    short int b = 0x3000;
    unsigned int unsignedRes;
    signed int signedRes;
    unsigned int ourRes;
    // Unsigned Multiplier
    unsignedRes = (unsigned short int) a * (unsigned short int) b;
    // Signed Multiplier
    signedRes = (short int) a * (short int) b;

    // Our Code using SIgned Multiplier
    ourRes = ((short int)a & ~(0xffffu << 16))*((short int)b & ~(0xffffu << 16));

    printf("Expected: 0x%x\nSigned: 0x%x\nResult: 0x%x",unsignedRes,signedRes,ourRes);
    getch();
    return 0;
}
4

1 回答 1

1

单独的分配short int b=0xc000;已经定义了实现(视频:ISO/IEC 9899:2018 6.3.1.3 p. 3),需要分两部分完成b = b1 * 2^15 + b0 = 0x1*2^15 + 0x4000(假设SHRT_MAX + 1 == 32768)。如果您像这样在两个部分中都这样做,并以结果是无符号数据类型的方式理解分配,并a*b == (a1 * 2^15 + a0) * (b1 * 2^15 + b0)通过使用unsigned int ret2结果和signed int临时变量来完成其余部分。

假设输入仅限于unsigned short int(unsigned因为0xc000) 的功能,并且所有类型都必须是有符号类型,但输出除外:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

int main(void)
{
   /*
      This whole thing has ben pulled apart for clarity and could (should!) be done
      in less lines of code.
      All implicit type conversions are made explicit.
      We also assume 2s complement (and a little bit more, to be honest).
    */

   /* 
       A and B limited to 0xffff to keep this code simple.
       If you want to get rid of these limits you need to count the bits
       of A and B and make sure that the sum does not exceed sizeof(int)*CHAR_BIT-1
    */
   signed int A = 0x7fff;
   signed int B = 0xc000;

   short int a0, a1;
   short int b0, b1;

   signed int shift = SHRT_MAX+1;

   unsigned int res1, res2;
   /* Additional temporary variables for legibility */
   signed int t0, t1, t2, t3;

   /* Check input range */
   if ((A > 0xffff) || (B > 0xffff)) {
      fprintf(stderr,"Input must not exceed 0xffff! A = 0x%x, B = 0x%x\n",A,B);
      exit(EXIT_FAILURE);
   }

   //unsigned multiplier
   res1 = (unsigned int)A * (unsigned int)B;

   //signed multiplier

   /* Compute  A*B == (a1 * shift + a0) * (b1 * shift + b0) */
   a0 = (short int)(A % shift);
   a1 = (short int)(A / shift);
   b0 = (short int)(B % shift);
   b1 = (short int)(B / shift);

   /*
      Multiply out for convenience:

      A*B == (a1 * 2^15 + a0) * (b1 * 2^15 + b0)
          ==  a1 * b1 *2^15 * 2^15
            + a0 * b1 * 2^15
            + a1 * b0 * 2^15
            + a0 * b0
    */
   /*
      Here a1 and b1 are either 0 (zero) or 1 (one) and (SHRT_MAX+1)^2 < INT_MAX
      so t0 cannot overflow.
      You should make use of that fact in production.
    */
   t0 = (signed int)a1 * (signed int)b1 * shift * shift; /* t0 in {0,shift^2} */
   t1 = (signed int)a0 * (signed int)b1 * shift; /* t1 in {0, a0 * shift} */
   t2 = (signed int)a1 * (signed int)b0 * shift; /* t2 in {0, b0 * shift} */
   t3 = (signed int)a0 * (signed int)b0; /* t3 can get larger than INT_MAX! */

   /* Cannot overflow because floor(sqrt(2^32-1)) = 0xffff and both A and B < 0xfff */
   res2 = (unsigned int)t0 + (unsigned int)t1 + (unsigned int)t2 + (unsigned int)t3;

   printf("res1: 0x%x %d\nres2: 0x%x %d\n",res1, res1, res2, res2);

   exit(EXIT_SUCCESS);
}

为了保持礼貌,作业的定义相当不明确,但由于我不知道是你的错,还是老师的错,还是变焦连接不好,所以我试着给你几个方向。如果不是预期的那样,您现在至少应该能够提出正确的问题。

于 2020-10-16T00:08:59.983 回答