目前共有4篇帖子。 内容转换:不转换▼
 
点击 回复
471 3
【程序】补码一位乘法——比较法
一派护法 十九级
1楼 发表于:2016-12-10 10:41
#include <stdio.h>

//#define SHOW

#pragma warning(disable:4996)

void binout(char *s, char v)
{
    char i;
    printf("%s", s);
    for (i = 0; i < 8; i++)
    {
        if (v & 0x80)
            putchar('1');
        else
            putchar('0');
        if (i == 0)
            putchar('.');
        v <<= 1;
    }
}

short multiply(char x, char y)
{
    // 所有寄存器全部采用算术移位
    // 且都采用双符号位
    char a = 0;
    char b2 = ~x + 1;
    char c = y;
    char cn = 0;
    char i;
    for (i = 1; i <= 8; i++) // 7位数值位需要8步操作
    {
        if ((c & 1) == 0 && cn == 1)
            a += x;
        else if ((c & 1) == 1 && cn == 0)
            a += b2;

        if (i != 8)
        {
            cn = c & 1; // c的最低位移入cn
            c >>= 1;

            // a的最低位移入c的最高位
            if (a & 1)
                c |= 0x80;
            else
                c &= 0x7f;
            a >>= 1;
        }

#ifdef SHOW
        binout("a=", a);
        binout(" c=", c);
        putchar('\n');
#endif
    }
    return (short)((a << 7) + ((c >> 1) & 0x7f));
}

void test(char a, char b)
{
    printf("%d * %d = %d\n", a, b, multiply(a, b));
}

void check(void)
{
    char a, b;
    short c;
    int cnt = 0;
    FILE *fp = fopen("result.txt", "w");
    if (fp == NULL)
        return;
    for (a = -64; a <= 63; a++)
    {
        for (b = -64; b <= 63; b++)
        {
            c = multiply((char)a, (char)b);
            if (a * b != c)
            {
                fprintf(fp, "Warning: %d * %d != %d\n", a, b, c);
                cnt++;
            }
            else
                fprintf(fp, "%d * %d = %d\n", a, b, c);
        }
    }
    fclose(fp);
    printf("Warning count: %d\n", cnt);
}

int main(void)
{
    check();
    test(-5, -3);
    test(-9, -16);
    test(-32, 1);
    test(-13, -11);
    return 0;
}
一派护法 十九级
2楼 发表于:2016-12-10 10:41
【运行结果】
Warning count: 0
-5 * -3 = 15
-9 * -16 = 144
-32 * 1 = -32
-13 * -11 = 143
一派护法 十九级
3楼 发表于:2016-12-10 10:46
注意:补码一位乘法中A、B寄存器必须采用双符号位。
因为11.1算术右移后是11.1,01.0算术右移后是00.1才对。
如果只有单符号位,那么1.1右移要想得到1.1必须采用算术移位,而1.0右移想要得到0.1就必须采用逻辑移位,这样就增加了硬件的复杂性。
不过,如果采用单符号位的同时规定A寄存器的移位方式为算术移位(signed char a),那么x=-127~127时能得到正确结果,只不过x=-128时,得出的结果符号是错误的,例如-128 x 1算出来是128,-128 x -1算出来是-128等等,这时只需要对结果取反再加一就行了(也就是变补)。
一派护法 十九级
4楼 发表于:2016-12-10 10:48
如果规定采用双符号位,那么x, y的取值范围就是-64~63。

回复帖子

内容:
用户名: 您目前是匿名发表
验证码:
(快捷键:Ctrl+Enter)
 

本帖信息

点击数:471 回复数:3
评论数: ?
作者:巨大八爪鱼
最后回复:巨大八爪鱼
最后回复时间:2016-12-10 10:48
 
©2010-2024 Arslanbar Ver2.0
除非另有声明,本站采用知识共享署名-相同方式共享 3.0 Unported许可协议进行许可。