面试官让你用C语言实现大数相乘,慌吗?

在之前的笔试题解析里面,我写了大数相加的问题,这里再剖析一个大数相乘,顾名思义,大数相乘就是这个数已经大到最大的数据类型都没有办法保存了。

我们看看最大的数据类型可以保存多大的数据。

#include 'stdio.h'
#include 'string.h'
int main()
{
    printf('0~%llu\n',(1ULL << sizeof(unsigned long long)*8) -1);
    return 0;
}

代码输出:

0~18446744073709551615

所以如果我们的数大于18446744073709551615 就会存在没有一个数据类型可以存储的情况,所以会有大数相乘的问题。

如何解决大数相乘问题?

看我下面的解题思路,这个思路可以也是从网上看到的。

  • 我们拿乘数的最低位,也就是2358 中的8 依次乘以被乘数的每一位,然后不做进位处理得到8 16 32 40.
  • 继续拿十位,百位,千位相乘,还是不进位
  • 然后依次列相加,相加的时候,也不做进位处理得到一个数据2 7 19 40 51 57 40.
  • 后面循环对上一步得到的数据进行进位处理,就会得到最终的结果。

代码实现

#include 'stdio.h'
#include 'string.h'

#define char_to_int(a) (int) (a - '0')
#define int_to_char(a) (char)(a + '0')

int main()
{
    char a[1000]={'1245'};
    char b[1000]={'2358'};
    char c[1000]={0};
    int i = 0, j = 0, k = 0;

memset(c,0,sizeof(c));

printf('%ld\n',strlen(a)-1);
    printf('%ld\n',strlen(b)-1);
    /*完成图片中的1,2步,结果从数组开头开始存放*/
    for (i = 0; i<strlen(a); i++)
    {
        k = i;
        for (j = 0; j<strlen(b); j++){
            c[k] += char_to_int(a[i]) * char_to_int(b[j]);
            k++;
        }
    }

printf('k=%d \n%.2d %.2d %.2d %.2d %.2d %.2d %.2d\n',k,c[0],c[1],c[2],c[3],c[4],c[5],c[6]);

/*完成图片中的3步,从后面往前面*/
    for (i = k-1; i>0; i--)
    {
        if (c[i] >= 10) {
            c[i-1] = c[i]/10 + c[i-1];
            c[i] = c[i]%10;
            printf('%.2d %.2d %.2d %.2d %.2d %.2d %.2d\n',c[0],c[1],c[2],c[3],c[4],c[5],c[6]);
        }
    }

/*输出*/
    for(i=0;i<k;i++)
        printf('%d',c[i]);putchar('\n');

return 0;
}

我这个代码直接参照我上面的图片例程编写,比较有参考性,大家在看代码的时候也需要注意一些细节,比如strlen获取的长度,k变量的大小等等。

程序输出:

33k=702 07 19 40 51 57 4002 07 19 40 51 61 0002 07 19 40 57 01 0002 07 19 45 07 01 0002 07 23 05 07 01 0002 09 03 05 07 01 002935710

随机验证下代码

验证的时候发现上面写的代码还有一些问题,顺便修改了下

#include 'stdio.h'
#include 'string.h'

#define char_to_int(a) (int) (a - '0')
#define int_to_char(a) (char)(a + '0')

int main()
{
    char a[1000]={'1561591985156415641419841516515919'};
    char b[1000]={'45645689129812561564159129821985125641'};
    unsigned long long c[1000]={0};
    int i = 0, j = 0, k = 0;

memset(c,0,sizeof(c));

/*完成图片中的1,2步,结果从数组开头开始存放*/
    for (i = 0; i<strlen(a); i++)
    {
        k = i;
        for (j = 0; j<strlen(b); j++){
            c[k] += char_to_int(a[i]) * char_to_int(b[j]);
            k++;
        }
    }
    /*完成图片中的3步,从后面往前面*/
    for (i = k-1; i>0; i--)
    {
        if (c[i] >= 10) {
            c[i-1] = c[i]/10 + c[i-1];
            c[i] = c[i]%10;
        }
    }

/*输出*/
    for(i=0;i<k;i++)
        printf('%llu',c[i]);putchar('\n');

return 0;
}

代码输出:

71279942302056620434200279768171066840415273983925010258196655791579079

但是遗憾的是,电脑自带的计算器不能计算这么大的数据,所以,我也不知道这个计算结果是不是正确的。

所以计算一个计算器可以计算的值

#include 'stdio.h'
#include 'string.h'

#define char_to_int(a) (int) (a - '0')
#define int_to_char(a) (char)(a + '0')

int main()
{
    char a[1000]={'1844674407'};
    char b[1000]={'3709551615'};
    unsigned long long c[1000]={0};
    int i = 0, j = 0, k = 0;

memset(c,0,sizeof(c));

/*完成图片中的1,2步,结果从数组开头开始存放*/
    for (i = 0; i<strlen(a); i++)
    {
        k = i;
        for (j = 0; j<strlen(b); j++){
            c[k] += char_to_int(a[i]) * char_to_int(b[j]);
            k++;
        }
    }
    /*完成图片中的3步,从后面往前面*/
    for (i = k-1; i>0; i--)
    {
        if (c[i] >= 10) {
            c[i-1] = c[i]/10 + c[i-1];
            c[i] = c[i]%10;
        }
    }

/*输出*/
    for(i=0;i<k;i++)
        printf('%llu',c[i]);putchar('\n');

return 0;
}

程序输出:

6842914925636017305

计算器输出

好吧,再来一次

#include 'stdio.h'
#include 'string.h'

#define char_to_int(a) (int) (a - '0')
#define int_to_char(a) (char)(a + '0')

int main()
{
    char a[1000]={'184467'};
    char b[1000]={'3709551615'};
    unsigned long long c[1000]={0};
    int i = 0, j = 0, k = 0;

memset(c,0,sizeof(c));

/*完成图片中的1,2步,结果从数组开头开始存放*/
    for (i = 0; i<strlen(a); i++)
    {
        k = i;
        for (j = 0; j<strlen(b); j++){
            c[k] += char_to_int(a[i]) * char_to_int(b[j]);
            k++;
        }
    }
    /*完成图片中的3步,从后面往前面*/
    for (i = k-1; i>0; i--)
    {
        if (c[i] >= 10) {
            c[i-1] = c[i]/10 + c[i-1];
            c[i] = c[i]%10;
        }
    }

/*输出*/
    for(i=0;i<k;i++)
        printf('%llu',c[i]);putchar('\n');

return 0;
}

程序输出

684289857764205

计算器输出

嗯,好像没有问题。

其他的大数相乘算法

我上面的代码不是最优解,但是可以让大家理解这个过程,如果想了解比较优秀的解决方案,可以网上找找资料。

https://en.wikipedia.org/wiki/Sch%C3%B6nhage%E2%80%93Strassen_algorithm

https://blog.csdn.net/u010983881/article/details/77503519


(0)

相关推荐

  • C语言中数组的总结

    #目录 # 一维数组的创建和初始化 一维数组的使用 一维数组在内存中的存储 指针的初步介绍 一维数组的指针访问 二维数组的创建和初始化 二维数组的使用 二维数组在内存中的存储 二维数组的指针访问 有关 ...

  • VS2019的调试功能学习(烫烫烫)

    我编写了个大数减法的程序但是会出现很奇怪的报错,然后我就一路百度... 现在我们尝试对以下代码用VS2019进行调试修改bug: //源文件main.cpp #include<stdio.h&g ...

  • 面试官问我CAS,我一点都不慌

    文章以纯面试的角度去讲解,所以有很多的细节是未铺垫的. 文章中写到的处理线程安全的思路每一项技术都可以写出一篇文章,AQS.Synchronized.Atomic...周末肝起来!下周再来给大家安排! ...

  • 女面试官“品”加一笔,是什么字研究生无法回答,输给高中生

    对于面试,每个人都看得非常重要,因为这是人生中非常重要的一件大事,如果面试顺利,自己就可以去自己喜欢的公司上班,对自己未来的发展是非常有利的,但是想面试通过哪有那么简单,很多大企业招聘的岗位竞争都非常 ...

  • 面试官:“你能为公司创造什么价值”,犀利问题,这么回答就对了

    面试时,当面试官问问出"你能为公司带来什么"或"你认为公司为什么会录用你"时,实质就是在问员工的价值,回答得好,能够绝地反击,说服面试官,直接拿到offer. ...

  • 女面试官“九”字加一笔,是什么字研究生回答“丸”被淘汰

    现代企业越来越看重面试这一个环节了,以前很多只用考笔试的单位,现在都加入了面试这个环节,而且的话,面试环节的占比分似乎都已经达到了和笔试的分数持平的一个状态.而且现在的面试不仅考察学识方面的东西,而且 ...

  • 女面试官 我例假来了, 能帮我接杯热水吗 男子的回答当场录用

    女面试官:我例假来了,能帮我接杯热水吗?男子的回答当场录用现代社会最难的就是找工作,不光是应届毕业生,很多已经工作过几年的朋友,依然面临这重新找工作的问题,而且现在找工作之所以难,是因为它已经不是简单 ...

  • 遇到这样的面试官发Offer,接了你可别后悔

    前两周溜出去面试,和我之前提到的一样,即使自己还没有想跳槽的想法,也要出去面试,看看自己的市场价值是多少. 很多人在面试求职过程中,认为自己总是被动的,被选择的,其实面试是一个双向选择的过程,我们也在 ...

  • 面试官:什么东西越热越爱出来?硕士生机智回答被成功录取

    面试应该是现如今非常常见的事情了,不论你去哪里工作,都需要事先面试一下,看看你这个人到底适不适合这个工作或者岗位. 所以面试对你对公司都是非常重要的一步,其实除了大公司之外,一些小的或者是私人公司,面 ...

  • 面试官:如何把一块钱的矿泉水卖出100块?年轻人回答被录取

    毕业后,许多大学生都想自己能幸运的找到一份好工作.拥有一份好工作,不但可以拿高薪和学习更多的经验.因此,许多人会选择去更大的企业.由于他们的专业管理系统和许多经验丰富的同事,他们可以学到很多东西,并增 ...

  • 面试官什么东西,左手能拿右手不能拿男子两个字回答,被录用

    有的时候,有些公司的面试官会给你们出一些十分古怪的问题,这些问题往往能难倒一片考生,有的问题太奇葩,让很多人一听到问题就傻眼了.小编的男闺蜜巩俐就在面试的时候,遇到了一个这样的问题. 那还是三个月前的 ...