Q2:大数据的加减乘除和公约公倍数

本文详细解析了一个简单的计算器程序源代码,包括加、减、乘、除、求余和最大公约数等功能的实现原理及步骤。通过使用C语言进行编程,作者深入探讨了整数运算、字符串输入处理、字符反转、借位运算、比较大小和判断正负数等关键概念。文章旨在为初学者提供一个全面理解计算器程序内部逻辑的实例。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *zero = "0";
char *minus = "-1";

void SetNum(char number[]){
    fgets(number, 201, stdin);
    number[(int)strlen(number)-1] = '\0';
}

char* Strrev(char func[], int t){
    while (!(func[t] > 48) || !(func[t] < 58)) t--;
    char *rev = (char *)malloc(t*sizeof(char));
    int i = 0;
    while (t >= 0)
    {
        rev[i++] = func[t--];
    }
    rev[i] = '\0';
    return rev;
}

void Swap(char *num1, char* num2){
    char *temp = (char *)malloc(201*sizeof(char));
    strcpy(temp, num1);
    strcpy(num1, num2);
    strcpy(num2, temp);
    free(temp);
}

int Minus(char *num1, char* num2){
    int mns = 0;
    if (num1[0] == '0') {
        num1[1] = '\0';
    }
    if (num2[0] == 0) {
        num2[1] = '\0';
    }
    if (num1[0] == '-') {
        mns += 1;
        memmove(num1, &num1[1], strlen(num1));
    }
    if (num2[0] == '-') {
        mns += 2;
        memmove(num2, &num2[1], strlen(num2));
    }
    return mns;
}
char* Add(char num1[], int len1, char num2[], int len2, int mns);
char* Sub(char num1[], int len1, char num2[], int len2, const char* identifier, int mns);


//Addition
char* Add(char num1[], int len1, char num2[], int len2, int mns){
    char *add = (char *)calloc(203, sizeof(char));
    if (mns == 1) {
        return Sub(num2, len2, num1, len1, "Sub", 0);
    }
    else if (mns == 2){
        return Sub(num1, len1, num2, len2, "Sub", 0);
    }
    int t;
    for (t = 0; len1 > 0 || len2 > 0; t++)
    {
        if (!add[t]){
            add[t] += '0';
        }
        if (len1 > 0){
            add[t] += num1[len1-1] - '0';
            --len1;
        }
        if (len2 > 0){
            add[t] += num2[len2-1] - '0';
            --len2;
        }
        if (add[t] > '9'){
            add[t] -= 10;
            add[t + 1] += '1';
        }
    }
    add = Strrev(add, t);
    if (mns == 3) {
        memmove(&add[1], add, strlen(add)+1);
        add[0] = '-';
    }
    return add;
}

//Subtraction
char* Sub(char num1[], int len1, char num2[], int len2, const char* identifier, int mns){
    int sub[202] = {0};
    int num2larger = 0;
    if (mns == 1) {
        return Add(num1, len1, num2, len2, 3);
    }
    else if (mns == 2){
        return Add(num2, len2, num1, len1, 0);
    }
    else if (mns == 3){
        return Sub(num2, len2, num1, len1, "Sub", 0);
    }

    if (len1 < len2)
    {
        num2larger = 1;
        if (!strcmp(identifier, "Div")) {
            return minus;
        }
        else if (!strcmp(identifier, "Rem")){
            memmove(&num1[1], num1, len1+1);
            num1[0] = 'R';
            return num1;
        }
    }
    else if (len1 == len2)
    {
        if (!strcmp(num1, num2)) {
            return zero;
        }
        else if (strcmp(num1, num2) < 0)
        {
            num2larger = 1;
            if (!strcmp(identifier, "Div")) {
                return minus;
            }
            else if (!strcmp(identifier, "Rem")){
                memmove(&num1[1], num1, len1+1);
                num1[0] = 'R';
                return num1;
            }
        }
    }

    if (num2larger)
    {
        Swap(num1, num2);
        int templen = len1;
        len1 = len2;
        len2 = templen;
    }//if num1 < num2

    int t;
    for (t = 0; len1 > 0 || len2 > 0; t++)
    {
        if (len1 > 0)
        {
            sub[t] += num1[len1 - 1] - '0';
            --len1;
        }
        if (len2 > 0) {
            sub[t] -= num2[len2 - 1] - '0';
            --len2;
        }
        if (sub[t] < 0)
        {
            sub[t] += 10;
            sub[t + 1] -= 1;

        }
    }//do divide

    char *subc = (char *)malloc(t * sizeof(char));
    for (int i = 0; i < t; i++) {
        subc[i] = sub[i] + '0';
    }
    subc[t] = '\0';
    subc = Strrev(subc, t+1);
    if (num2larger) {
        Swap(num1, num2);
        memmove(&subc[1], subc, strlen(subc)+1);
        subc[0] = '-';
    }//exchange num1, num2 back
    return subc;
}

//Multiplication
char* Multi(char num1[], int len1, char num2[], int len2, int mns){
    int Mult[401] = {0};
    int digit[200];
    if (!strcmp(num1, "0") || !strcmp(num2, "0")) {
        return zero;
    }//等于0的处理

    int length1 = len1;
    for(int t = 0; length1 > 0; ++t)
    {
        digit[t] = num1[length1-1] - '0';
        int length2 = len2;
        for (int i = t; length2 > 0; ++i){
            Mult[i] += digit[t] * (num2[length2-1] - '0');
            if (Mult[i] > 9){
                Mult[i+1] += Mult[i] / 10;
                Mult[i] %= 10;
            }
            length2--;
        }
        length1--;
    }//计算过程

    char *MultC = (char *)malloc(404 * sizeof(char));
    int i;
    for (i = 0; i < len1 + len2 + 1; i++)
    {
        MultC[i] = Mult[i] + '0';
    }
    MultC[i] = '\0';
    MultC = Strrev(MultC, (int)strlen(MultC));
    if (mns == 1 || mns == 2) {
        memmove(&MultC[1], MultC, strlen(MultC)+1);
        MultC[0] = '-';
    }
    return MultC;
}

//Division
char* Div(const char num1[], int len1, char num2[], int len2, char *identifier, int mns){
    char *zero = "0";
    if (!strcmp(num2, "0")) {
        printf("wrong dividend!\n");
        return NULL;
    }
    if (!strcmp(num1, "0")) {
        return zero;
    }//if num1 == 0 || num2 == 0

    char *num1cpy = (char *)malloc(len1*sizeof(char));
    strcpy(num1cpy, num1);
    long long int result = 0;

    do{
        num1cpy = Sub(num1cpy, (int)strlen(num1cpy), num2, len2, identifier, 0);

        len1 = (int)strlen(num1cpy);
        if(strcmp("0", num1cpy) == 0)
        {
            if (!strcmp(identifier, "Rem")){
                return zero;
            }
            else {
                result++;
            }
            break;
        }
        else if(strcmp("-1", num1cpy) == 0){
            break;
        }
        else if (!strncmp("R", num1cpy, 1)) {
            return &num1cpy[1];
        }
        result++;
    }while (1);

    char* cresult = (char *)malloc(20*sizeof(char));
    if (mns == 1 || mns == 2) {
        result = -result;
    }
    sprintf(cresult, "%lld", result);

    return cresult;
}

//Great Common Divisor
char* GCD(char num1[], int len1, char num2[], int len2, int mns){
    char *num1cpy = (char* )malloc((len1+1)*sizeof(char));
    char *num2cpy = (char* )malloc((len2+1)*sizeof(char));
    strcpy(num1cpy, num1);
    strcpy(num2cpy, num2);

    char *rem = (char *)malloc(201 * sizeof(char));
    char *result = (char *)malloc(201 * sizeof(char));
    while (1) {
        result = Div(num1cpy, (int)strlen(num1cpy), num2cpy, (int)strlen(num2cpy), "Div", 0);
        rem = Div(num1cpy, (int)strlen(num1cpy), num2cpy, (int)strlen(num2cpy), "Rem", 0);
        if (strcmp(rem, "0")) {
            strcpy(num1cpy, num2cpy);
            strcpy(num2cpy, rem);
        }
        else break;
    }
    if (mns == 1 || mns == 2) {
        memmove(&num2cpy[1], num2cpy, strlen(num2cpy)+1);
        num2cpy[0] = '-';
    }
    return num2cpy;
}

int main(){
    char num1[202], num2[202];
    char num1bak[202], num2bak[201];
    printf("Enter first number:\n");
    SetNum(num1);
    strcpy(num1bak, num1);
    printf("Enter Second number:\n");
    SetNum(num2);
    strcpy(num2bak, num2);
    int mns = Minus(num1, num2);
    int len1 = (int)strlen(num1);
    int len2 = (int)strlen(num2);

    putchar('\n');
    printf("%s + %s = %s\n", num1bak, num2bak, Add(num1, len1, num2, len2, mns));
    printf("%s - %s = %s\n", num1bak, num2bak, Sub(num1, len1, num2, len2, "Sub", mns));
    char *product = Multi(num1, len1, num2, len2, mns);
    printf("%s * %s = %s\n", num1bak, num2bak, product);
    if (strcmp(num2, "0") != 0){
        printf("%s / %s = %s\n", num1bak, num2bak, Div(num1, len1, num2, len2, "Div", mns));
        if (mns != 1 && mns != 2){
            char *gcd = GCD(num1, len1, num2, len2, mns);
            printf("gcd(%s, %s) = %s\n", num1bak, num2bak, gcd);
            mns = Minus(gcd, product);
            char *lcm = Div(product, (int)strlen(product), gcd, (int)strlen(gcd), "Div", mns);
            printf("lcm(%s, %s) = %s\n", num1bak, num2bak, lcm);
        }
    }

    return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值