【小白向C语言】从一到n的累加(大数版)学习笔记

只是在一次上课中听到老师说起用C实现从1到100万的累加,于是再也忘不掉2333
于是作为小小白的我开始了一段艰辛的学习历程
看懂本文所需的主要知识储备:
1.if判断语句
2.数组
3.for循环和循环镶嵌结构
话不多说,在此是我的思考与学习过程,具体分为三个步骤

1.实现从1到n的累加

这个应该很好理解,只需要简单利用数学公式即可

/ *1到n的累加*/
#include<stdio.h>
#include<stdlib.h>
int main()
{
    unsigned long sum,n;
    printf("please input n = ");
    scanf("%u",&n);
    sum = (n+1)*n/2;//利用求和公式
    printf("the sum is %u \n",m);
    system("pause");
}

实现这一步之后,我们就大概有一个基本思路了。

2.大数运算(乘法)的学习

先po上我学习大数乘法参考的文章,讲的很细,适合小小白
我学习大数乘法的文章
https://blog.csdn.net/lisp1995/article/details/52316466
但是我们并不能直接生搬硬套,我们一定要学会其中的各种技巧与算法思路,再将它们合适地运用在我们的核心式子中sum = (n+1)*n/2

(1)实现大数n*n
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//定义全局变量!!!
char n[100];
int x[110], z[210];
int main()
{
    int len1, i, j;
    printf("please input n = ");
    gets(n);
    len1 = strlen(n);
    //实现大数n*n
    for (j = 0, i = len1 - 1; i >= 0; i--) //将字符转换为数字,并倒序保存(乘法先从末位开始)
    {
        x[j++] = n[i] - '0'; //字符串与整数的储存差异
    }
    for (i = 0; i < len1; i++) //模拟笔算竖乘,进位在下一步统一处理
    {
        for (j = 0; j < len1; j++)
        {
            z[i + j] += x[i] * x[j]; //将两数每一位相乘(重点理解)
        }
    }
    for (i = 0; i < 200; i++) //进行进位处理
    {
        if (z[i] >= 10)
        {
            z[i + 1] += z[i] / 10; //进位
            z[i] = z[i] % 10;      //保留个位数
        }
    }

在这里因为我们是两个相同大数的相乘所以只需定义一个字符串数组,其他的都可以套用。
标注重点理解的那一行代码,如果小小白们不理解,可以先手算一些数字,认真体会笔算步骤,因为这种方法就是在模拟笔算的过程

(2)大数加法实现n*n +n

现在z[210]是大数n*n,x[110]是大数n。相信对于大数乘法中模拟笔算的理解,我们很快能想到我们只要实现倒序的每一位的相加再进位就可以了。
还需要注意的是,这里x与z数组大小不相等,那么我们只需要将更小的数组处理完,另一个数组的余下部分不做处理即可。

    //实现大数n*n + n
    for (i = 0; i < 200; i++)
    {
        if (i <= 100)//只需要将x数组处理完
        {
            z[i] += x[i];
            if (z[i] >= 10)
            {
                z[i] -= 10; //保留个位
                z[i + 1]++; //满十进一
            }
        }
    }

(这里的进位处理其实只是上步进位处理的简化)

(3)实现除2

到这里已经快要接近胜利了,这一步其实也是沿用上述模拟笔算的思想,应该没有什么理解难度。(这个并不属于大数除法)

//实现n*(n+1)/2
    for (i = 200; i >= 0; i--) //模拟笔算做除法
    {
        z[i - 1] = z[i - 1] + (z[i] % 2) * 10;
        z[i] = z[i] / 2;
    }

3.输出步骤

其实是套用,haha。
我的理解是把第一个非零数字之前的所有的z[i]=0储存在循环里,再输出余下的数字。

    //输出时的处理
    for (i = 200; i >= 0; i--) //把第一个非零数之前的所有0去掉
    {
        if (z[i] == 0)
            continue;
        else
            break;
    }
    printf("the sum is ");
    for (; i >= 0; i--) //倒序输出
    {
        printf("%d", z[i]);
    }
    printf("\n");
    system("pause");
}

大功告成!

以下是完整代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//定义全局变量!!!
char n[100];
int x[110], z[210];
int main()
{
    int len1, i, j;
    printf("please input n = ");
    gets(n);
    len1 = strlen(n);

    //实现大数n*n
    for (j = 0, i = len1 - 1; i >= 0; i--) //将字符转换为数字,并倒序保存(乘法先从末位开始)
    {
        x[j++] = n[i] - '0'; //字符串与整数的储存差异
    }
    for (i = 0; i < len1; i++) //模拟笔算竖乘,进位在下一步统一处理
    {
        for (j = 0; j < len1; j++)
        {
            z[i + j] += x[i] * x[j]; //将两数每一位相乘
        }
    }
    for (i = 0; i < 200; i++) //进行进位处理
    {
        if (z[i] >= 10)
        {
            z[i + 1] += z[i] / 10; //进位
            z[i] = z[i] % 10;      //保留个位数
        }
    }
    //实现大数n*n + n
    for (i = 0; i < 200; i++)
    {
        if (i <= 100)
        {
            z[i] += x[i];
            if (z[i] >= 10)
            {
                z[i] -= 10; //保留个位
                z[i + 1]++; //满十进一
            }
        }
    }

    //实现n*(n+1)/2
    for (i = 200; i >= 0; i--) //模拟笔算做除法
    {
        z[i - 1] = z[i - 1] + (z[i] % 2) * 10;
        z[i] = z[i] / 2;
    }
    //输出时的处理
    for (i = 200; i >= 0; i--) //删除0的前缀
    {
        if (z[i] == 0)
            continue;
        else
            break;
    }
    printf("the sum is ");
    for (; i >= 0; i--) //倒序输出
    {
        printf("%d", z[i]);
    }
    printf("\n");
    system("pause");
}

小小白的第一篇原创,请多多支持。
如有错误请大神们不吝赐教!先谢过!

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值