#include <stdio.h>
#pragma warning(disable:4996) // 消除scanf警告
// 原码一位乘法函数 // 返回值为16位原码表示的积 short multiply(char x, char y) { char i; char rs[2]; unsigned char a = 0; // 存放部分积累加和, 初始值为0 unsigned char b = x & 0x7f; // 存放不带符号位的x unsigned char c = y & 0x7f; // 存放不带符号位的y for (i = 0; i < 7; i++) // 8位有符号数一共有7位数值位 { if (c & 1) a += b; c >>= 1;
// 将A的末位移入C的高位 // 注意unsigned char的移位是逻辑移位, char是算术移位 if (a & 1) c |= 0x80; a >>= 1; }
// 两个7位的数相乘, 积为14位, 加上符号位就是15位 // 而short有16位, 所以次高位一定为0 rs[0] = c; // c的高7位为低位部分 rs[1] = a; // a为高位部分 *(unsigned short *)rs >>= 1; // 右移空出次高位, unsigned表示逻辑移位(即空位一定添0) // 次高位(第14位)恒为0
// 异号得负 if (((x ^ y) & 0x80) != 0) rs[1] |= 0x80; return *(short *)rs; }
/*********** 以下为测试代码 ***********/ // 32位补码转8位原码 char convert(int n) { char c = (char)(n & 0xff); if (c < 0) { c--; c ^= 0x7f; // 低7位反转 } return c; }
// 16位原码转32位补码 int restore(short s) { int n = s & 0x7fff; if (s & 0x8000) n = ~n + 1; return n; }
int main(void) { int n; // 输入的整数个数 int xd, yd; // 以补码表示的两个32位的乘数 short result; // 16位计算结果(原码表示)
printf("请输入两个数: "); n = scanf("%d%d", &xd, &yd); if (n != 2) { puts("数字格式不正确!"); return 0; } else if (xd < -127 || xd > 127 || yd < -127 || yd > 127) { // 注: 虽然char能够保存-128, 但是这个数无法用8位的原码表示 puts("这是一个8位的原码乘法器,所以输入的数必须在-127~127之间!"); return 0; }
result = multiply(convert(xd), convert(yd)); // 计算 printf("计算结果: %d\n", restore(result)); return 0; } /*************************************/
|