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