小型大数模拟

闲着没事干,帮别人写个c语言的作业,就顺便用来写这博客好了。
题目是用字符串来表示浮点数(字符串长度为30,后10位是小数位),实现加减乘除法。我觉得这和大数类似,用char来表示一个数字,虽然有点浪费空间,不过优化,思路不变就无关紧要了,思路对了就行。
由于我的懒惰和她们老师并不要求写浮点数除法,我也就没写了,正负数的判断也没写,内存释放也没写,怕内存泄漏的话就后面自己free就好了也没多难,因为她们题目要求返回char *所以我malloc之后就没free。然后读取数据也比较简单,我也不能不让她什么偶不写嘛,所以我就没写获取数据,scanf就行,也没多难。
ps:我的程序是把第20位作为整数的个位,19位是十位。。。第21位就是小数的第一位,22是小数第二位。。。
加减法没有难点,乘法难点是在相乘后的数字所在的位数,除法的难点就是取余然后放到它该在的位置上,余数继续往后算。就这样。

#include<stdio.h>
#include<memory.h>
#include<stdlib.h>
#include<string>
bool biger_then(const char* a, const char *b) {
    //大小判断
    int temp = 0;
    while (a[temp] == '0'&&b[temp] == '0' || a[temp] == b[temp]) temp++;
    if (a[temp] - b[temp] > 0)
        return true;
    else
        return false;
}
char * getnum(char *result,int flag) {
    //将结果整合成人们习惯的表达式
    char *p = (char *)malloc(31);
    memset(p, 0, 31);
    int i = 0, j = 0;
    if (flag == 0)
        j = 0;
    else {
        p[j++] = '-';
    }
    while (result[i] == '0' && i < 20)
        i++;
    while (i < 20)
        p[j++] = result[i++];
    if (p[0] == 0 &&flag==0 || p[1]== 0 && flag == 1 )
        p[j++] = '0';
    p[j++] = '.';
    while (i < 30)
        p[j++] = result[i++];
    p[j] = '\0';
    return p;
}
void creatnum(char *input) {
    //将字符串改成要求的格式
    char p[30];
    for (int i = 0; i < 30; i++)
        p[i] = '0';
    if (input == NULL)
        return;
    int point=0;
    while (input[point]!='\0'){
        if (input[point] >= '0'&&input[point] <= '9' || input[point] == '.') {
            if (input[point] != '.')
                point++;
            else
                break;
        }else{
            printf("input error");
            return;
        }
    }
    int i = point - 1, j = 19;
    char temp = '0';
    for (; i >= 0&&j >= 0; j--, i--)
        p[j] = input[i];
    for (i = point + 1, j = 20; input[i] != '\0'&&j < 30; j++, i++)
        p[j] = input[i];
    for (i = 0; i < 30; i++)
        input[i] = p[i];
    input[30] = '\0';
}
char * add(const char *a, const char *b) {
    //两个符合要求的字符串的加法,懒得拓展字符串加整数了
    if (b == NULL || a == NULL) {
        printf("input error\n");
        exit(1);
    }
    char result[31];
    for (int i = 0; i < 30; i++)
        result[i] = '0';
    result[30] = '\0';
    int add_flag = 0;
    for (int i = 29; i >= 0; i--) {
        int temp = a[i] - '0' + b[i] - '0' + add_flag;
        if (temp > 9) {
            temp -= 10;
            add_flag += 1;
        }
        else
            add_flag = 0;

        result[i] = temp + '0';
    }
    return getnum(result,0);
}
char * sub(const char *a, const char *b){
    //两个符合要求的字符串的减法,同样懒得拓展字符串减整数了
    if (b == NULL || a == NULL) {
        printf("input error\n");
        exit(1);
    }
    char result[31];
    const char *p, *q;
    for (int i = 0; i < 30; i++)
        result[i] = '0';
    result[30] = '\0';
    int flag = 0,j;
    if (biger_then(a,b)) {
        p = a;
        q = b;
    }else{
        p = b;
        q = a;
        flag = 1;
    }
    for (int i = 0; i < 30; i++) {
        if (p[i] - q[i] >= 0)
            result[i] = p[i] - q[i] + '0';
        else {
            j = i - 1;
            while (result[j] == '0')
                j--;
            result[j++]--;
            while (j > i);
            result[j++] = '9';
            result[i] = p[i] - q[i] + 10 + '0';
        }
    }
    return getnum(result,flag);
}
char * div(const char *a, int b) { 
    //除以整数,小数,因为怕被除数过大给我整越界了,所以就写个简单的字符串除以整数
    if (b == 0||a == NULL) {
        printf("input error\n");
        exit(1);
    }
    int i, down = 0,flag=0;
    if (b < 0) {
        flag = 1;
        b = -b;
    }
    char result[31];
    for (i = 0; i < 30; i++)
    {
        result[i] = (a[i] + down * 10 - '0') / b + '0';
        down = a[i] - '0' + down * 10 - (result[i] - '0' ) * b;
    }
    return getnum(result, flag);
}
char * mul(const char *a, const char *b) {
    //两个符合要求的字符串的乘法,没错,我还是懒得拓展字符串乘整数了
    char temp1[31], temp2[31], result1[31],result2[31];
    for (int i = 0; i < 30; i++)
        temp1[i]=result1[i]= temp2[i] = result2[i] = '0';
    for (int i = 0; i < 20; i++)
        temp1[i] = b[i];
    int num = 0;//小数点偏移量。
    for (int i = 29; i >= 20; i--) {
        if (b[i] != '0') {
            int j = 19;
            while (i >= 20) {
                temp2[j--] = b[i--];
                num++;
            }
        }
    }
    temp1[30] = temp2[30]= result1[30] = result2[30] = '\0';
    int  i, j, up, t;
    for (i = 29; i >= 0; i--) { //整数部分
        up = 0;
        for (j = 19; j >= 0; j--) {
            t = (a[i] - '0')*(temp1[j] - '0') + (result1[i + j - 19]-'0') + up;
            if (t >= 10) {
                up = t / 10;
                if(i + j - 19 >=0&& i + j - 19 < 30)
                    result1[i + j - 19] = t % 10 + '0';
            }
            else {
                up = 0;
                if (i + j - 19 >= 0 && i + j - 19 < 30)
                    result1[i + j - 19] = t + '0';
            }
        }
    }
    for (i = 29; i >= 0; i--) { //小数部分
        up = 0;
        for (j = 19; j >= 0; j--) {
            t = (a[i] - '0')*(temp2[j] - '0') + (result2[i + j - 19] - '0') + up;
            if (t >= 10) {
                up = t / 10;
                if (i + j - 19 >= 0 && i + j - 19 < 30)
                    result2[i + j - 19] = t % 10 + '0';
            }
            else {
                up = 0;
                if (i + j - 19 >= 0 && i + j - 19 < 30)
                    result2[i + j - 19] = t + '0';
            }
        }
    }
    //对小数部分的结果进行偏移。
    for (int i = 29; i >= 0; i--) {
        if (i + num < 30) {
            result2[i + num] = result2[i];
            result2[i] = '0';
        }
    }
    //将result1和result2合起来就是结果,调用加法函数。
    return add(result1, result2);
}
int main()
{
    //没有进行输入负数字符串的判断,只进行了正数的合法性输入的判断。
    //这个没有释放heap上的内存,容易导致内存泄漏,一般情况得自己释放
    char i[31] = "2.2";
    char j[31] = "0.3";
    printf("a=%s b=%s\n", i,j);
    creatnum(i);
    creatnum(j);
    printf("a + b = %s\n", p);
    p = sub(i, j);
    printf("a - b = %s\n", p);
    p = mul(i, j);
    printf("a * b = %s\n", p);
    int t=-3;
    char *q = div(i, t);
    printf("a / %d = %s\n", t ,q);
    if (biger_then(i, j))
        printf("a>b");
    else
        printf("a<=b");
    return 0;
}

不太会说话,这就是个思路的问题实现起来难度并不大,语言难度挺小的。小数除法我还是不太会算。。。有空再研究吧

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值