Unsigned Multiplication using Signed Multiplier

偶尔善良 提交于 2021-01-29 07:18:08

问题


I have been assigned with a task to perform unsigned multiplication using signed multiplier. Despite multiple attempts, I couldn't get it. Is it possible to do this?

Code:

#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;
}

This is the code provided.

Current Output:

res1: 0x5fff4000 1610563584 
res2: 0xe0004000 -536854528

Expected Output:

res1: 0x5fff4000 1610563584 
res2: 0x5fff4000 1610563584 

Working Code:

#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;
}

回答1:


The assignment short int b=0xc000; alone is already implementation defined (vid.: ISO/IEC 9899:2018 6.3.1.3 p. 3) and would need to be done in two parts b = b1 * 2^15 + b0 = 0x1*2^15 + 0x4000 (assuming SHRT_MAX + 1 == 32768 ). If you do both in two parts like that and understand the assignment in such a way that the result is an unsigned data type and do a*b == (a1 * 2^15 + a0) * (b1 * 2^15 + b0) by using unsigned int ret2 for the result and signed int temporary variables for the rest.

Assuming that the input is restricted to the capabilities of an unsigned short int (unsigned because of 0xc000) and that all types must be signed types with the exception of the output:

#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);
}

The assignment is rather under-defined, to keep it polite, but as I do not know if it is your fault, the teacher's fault or a bad zoom-connection I tried to give you a couple of directions. If it wasn't wat was expected you should at least be able to ask the right questions now.



来源:https://stackoverflow.com/questions/64375928/unsigned-multiplication-using-signed-multiplier

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!