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