算法-大数乘法(16进制)(C语言实现)

由来

由于工作中用到,自己在网上找了一些大数乘法源码,都没有符合我要求的。所以自己造轮子,实现了一个。

分析过程

仿照我们小学学过的10进制乘法算式,来实现的大数乘法。
先举一个例子:234 * 567


普通大数乘法图片

这是我们最普通的乘法算式,对于程序实现起来还有点难,因此我们再继续计算分析:
注:图中的小数字,不是次方,只是进位的数


进位不加的大数乘法图片

这个计算过程跟上图的区别就是加法跟乘法分开来计算,我在做乘法部分的时候,只是单纯的计算乘法,没有做加法,把进位的数标记出来,最后把在同一列的数字统统加起来,该进位的进位,最后起算出来结果。
写到这里大概就清晰了,我们先列个数组。

//用伪代码数组表示数:234567
a[3] = {2, 3, 4}
b[3] = {5, 6, 7}

下图为数组中表示形式


进位不加的大数乘法图片

程序讲解

以上讲解为分析过程,我用我们常用的10进制作为分析,在下面源码中用到了0x100进制,其实原理是一样的,一个unsigned char类型变量,正好最大可以支持到0xFF。

程序源码

以下是大数乘法编译过得程序

#include <stdio.h>  

typedef unsigned char u8;
typedef unsigned int u32;

#define N 32
#define CARRYNUM 0x100

void BigMul(u8* res_high, u8* res_low, u8 *a, u8 *b)
{
    int ai, bi, ri;
    u32 tmp;
    u32 res[N*2] = {0};

    //乘法计算核心部分
    for(ai = N-1; ai >= 0; ai--)    //a从后往前,低位往高位乘起来
    {
        for(bi = N-1; bi >=0; bi--)    //b从后往前,低位往高位乘起来     
        {
            tmp = a[ai] * b[bi];
            res[ai+bi+1] += (tmp % CARRYNUM); //取低位,并累加所有相同下标    
            res[ai+bi] += (tmp / CARRYNUM);   //取高位,并累加所有相同下标
        }
    }
    for(ri = (2*N)-1; ri > 0; ri--)
    {
        if(res[ri] > CARRYNUM-1)    //从res低位开始判断,若大于0x100,向高位进位
        {
            res[ri-1] += (res[ri]/CARRYNUM);    //低位 进位数加到 高位
            res[ri] = res[ri]%CARRYNUM;         //低位数的进位去掉,保留低位数的低位
        }
    }

    //输出
    for(ri = 0; ri < 2*N; ri++)
    {
        if(ri < N)
            res_high[ri] = res[ri];
        else
            res_low[ri-N] = res[ri];
    }
    return;
}

void print_num(u8* res_high, u8* res_low)
{
    int i = 0;
    for(i = 0; i < N; i++)
    {
        printf("%02x ", res_high[i]); 
    }

    for(i = 0; i < N; i++)
    {
        printf("%02x ", res_low[i]); 
    }
}

void main()  
{  
    //数组[0]数据高位, [31]数据低位
    //u8 a[N] = {0xDE,0x2A,0x7C,0xF8,0x48,0x24,0xCF,0xA0,0xCE,0xD7,0x16,0xAD,0xF5,0xD4,0x7D,0xE9,0x3D,0xFA,0x31,0xEB,0x69,0x26,0xB7,0xF7,0xDF,0x69,0xBD,0xE0,0x1F,0x9E,0xDB,0x0D};
    //u8 b[N] = {0x5A,0x1C,0x23,0x99,0x87,0x70,0x82,0xB8,0x12,0x50,0xCB,0x2A,0x7F,0x8B,0x74,0x53,0x5D,0x38,0x05,0xB5,0xB0,0xFE,0x8C,0x0E,0xF1,0xE7,0x73,0x15,0x47,0xD4,0x9A,0xA2};

    //u8 a[N] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
    //u8 b[N] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

    //u8 a[N] = {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11};
    //u8 b[N] = {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11};

    //u8 a[N] = {0x00,0x00,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11};
    //u8 b[N] = {0x00,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11};

    u8 a[N] = {0x00,0x00,0x00,0xD1,0xB8,0xAA,0x3E,0x1B,0x32,0xDB,0xB9,0x5A,0x13,0xB3,0x52,0x79,0x10,0x22,0x1E,0x47,0x49,0x00,0x8D,0xF9,0xA3,0x40,0xE6,0x9D,0x68,0x38,0x2C,0x58};
    u8 b[N] = {0x00,0x00,0x00,0x00,0x00,0xBF,0xB7,0x4C,0x0C,0xBF,0x09,0x13,0x1E,0x1E,0xEC,0x72,0x21,0x60,0xE5,0x5F,0xAD,0xCF,0x8E,0x50,0x50,0xE7,0xBA,0xF5,0xE9,0x6B,0x3D,0x5E};


    u8 res_high[N] = {0};
    u8 res_low[N] = {0};
    int i = 0;

    BigMul(res_high, res_low, a, b); 

    print_num(res_high, res_low);

}  

以下是执行结果:

00 00 00 00 00 00 00 00 9d 0e f0 53 4c 63 04 72 6f 67 38 02 90 dd a1 d9 3a 25 0d df d2 4a d4 b4 7b 5a 3a 1c e7 9e db 99 6e 16 0d 00 2e b8 06 be bd 5c c0 38 37 8a 41 ff 21 d0 3f b0 47 f9 40 50 请按任意键继续…

大数乘法代码 下载地址

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ha-Ha-Interesting

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值