大数相乘

受计算机变量大小限制。当乘数过大时,计算机无法进行乘法,必须自己想法予以实现。

本程序可处理带小数的大数乘法运算。

运算结果正确。可以将前几年破解的 RSA-158 密码来试验


// 前几年破解的 RSA-158 密码是这样因数分解的
// result :39505874583265144526419767800614481996020776460304936454139376051579355626529450683609727842468219535093544305870490251995655335710209799226484977949442955603
// part1:3388495837466721394368393204672181522815830368604993048084925840555281177

// part2:11658823406671259903148376558383270818131012258146392600439520994131344334162924536139

运算时,先将乘数都反转。即倒着乘,主要是防止进位时没有空间了。最后将结果也反转输出即可

以15*15为例

第一步,反转后变为 51*51
第二步,相乘(不进位) 25 10 1,
第三步,进位 25向10进2位后变为5,12向1进1位后变为2,最后结果为522
第四步,反转 522->225,即15*15的结果。
如果有小数,记录总的小数位数,将两个数变为正数后进行上面的步骤,最后加上小数位即可。


源代码如下:

 //

//   bignum.c

//  完成有小数位的俩个大数的乘法

//  Created by GPH on 13-7-14.

//  Copyright (c) 2013年 GPH. All rights

//


#include<stdio.h>

#define NUM_RESULT 200

#define NUM_PART 100


void convert(char *a,int *b);

void bigNumberMul(char *a,char*b,int count);

int split(char *a,char*b);



//先将字符串反转。

//再字符型数字转为数字,存在整形数组中,为乘法做准备

//若是高位放在数组头部,则进位时可能没有空间

//所以将低位放在数组头部。高位放尾部。

//输出时倒序即可

void convert(char *a,int *b)

{

    int l = strlen(a);

    char temp;
    for (int i = 0; i < l/2; i++)

    {

        temp = a[i];

        a[i] = a[l-i-1];

        a[l-i-1] = temp;

    }

    for (int i = 0; i < l; i++)

    {

        b[i] = a[i]-'0';

    }

}


//逐位相乘,再进位

void bigNumberMul(char *a,char*b,int count)

{

    int ih[NUM_RESULT]={};

    int ia[NUM_PART];

    int ib[NUM_PART];

    convert(a,ia);

    convert(b,ib);

    for (int i = 0; i < strlen(a); i++)

    {

        for ( int j = 0; j < strlen(b); j++)

        {

            ih[i+j] += ia[i]*ib[j];

        }

    }

    

    //逐次进位

    for (int i = 0; i < NUM_RESULT-1; i++)

    {

        ih[i+1] += ih[i]/10;

        ih[i] %= 10 ;

    }

    

    int i;

    for ( i = NUM_RESULT-1;i >= 0 ; i--)

    {

        if (ih[i])

        {

            break;

        }

    }

    for ( ;i >= 0 ; i--)

    {

        if(i == count-1)

        {

            printf(".");

        }

        printf("%d",ih[i]);

        

    }

}


//统计小数位共多少。并删除"."号

//用来最终输出时,确定小数位数

int split(char *a,char*b)

{

    int sum = 0;

    for (int i = 0;i< strlen(a) ; i++)

    {

        if(a[i] == '.')

        {

            //前移,删除'.'

            for (int j = i; j < strlen(a)-1 ; j++)

            {

                a[j] = a[j+1];

            }

            sum += strlen(a)-i-1;

            a[strlen(a)-1] = '\0';

            break;

        }

    }

    for (int i = 0;i< strlen(b) ; i++)

    {

        if(b[i] == '.')

        {

            //前移,删除'.'

            for (int j = i; j < strlen(b)-1 ; j++)

            {

                b[j] = b[j+1];

            }

            sum += strlen(b)-i-1;

            b[strlen(b)-1] = '\0';

            break;

        }

    }

    return sum;

}


int main(int argc, const char * argv[])

{

    char a[NUM_PART];

    char b[NUM_PART];

    int count;

    printf("input:");

    scanf("%s",a);

    printf("input:");

    scanf("%s",b);

    printf("\n");

    getchar();

    count = split(a,b);//统计小数位
    
    bigNumberMul(a,b,count);

    printf("\n");

    return 0;

}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值