结对编程-四则运算

要求:小学老师要每周给同学出300道四则运算练习题。

简易版:式子中只有一个一个运算符号。

首先定义一个时间种子,用于生成0-100的随机数,以及生成四个运算符号,实现如下

char op[] = { '+','-','*','/' };//运算符号
int a, t, b;
void random() {//随机生成数字
    srand(time(0));//时间种子
    a = rand() % 101;//生成0到100之间的随机数
    t = rand() % 4;//生成运算符下标
    b = rand() % 100 + 1;//由于分母不能为0,所以得生成1-100;
    std::cout << a << op[t] << b << "=";
}

其次就是直接判断是什么运算符号,然后直接计算即可,需要注意的是由于有除法可能会存在小数点的精度误差,所以为了保证答案正确,所以在判断打哪是否正确的时候判断来两个数的大小是否小于某个精度

double calc() {
    if (op[t] == '+') {
        return a + b;
    }
    else if (op[t] == '-') {
        return a - b;
    }
    else if (op[t] == '/') {
        return (double)a / (double)b;
    }
    else if (op[t] == '*') {
        return a * b;
    }
}

random();//获取表达式
double ans;
std::cin >> ans;

if (fabs(calc() - ans) <= 1e-2){//可能会出现精度误差由于除法的存在
    std::cout << "回答正确!\n";
    ok++;
}
else {
    std::cout << "回答错误!\n正确答案为:" << calc() << "\n";
}

然后在加入一些提示用于,简易的计算器就完成了。

#include<iostream>
#include<string>
char op[] = { '+','-','*','/' };//运算符号
int a, t, b;
void random() {//随机生成数字
    srand(time(0));//时间种子
    a = rand() % 101;//生成0到100之间的随机数
    t = rand() % 4;//生成运算符下标
    b = rand() % 100 + 1;//由于分母不能为0,所以得生成1-100;
    std::cout << a << op[t] << b << "=";
}

double calc() {
    if (op[t] == '+') {
        return a + b;
    }
    else if (op[t] == '-') {
        return a - b;
    }
    else if (op[t] == '/') {
        return (double)a / (double)b;
    }
    else if (op[t] == '*') {
        return a * b;
    }
}

int main() {
    int num; 
    std::cout << "请输入你要挑战的算术式的数量:\n";
    std::cin >> num;
    int sum = num;
    int ok = 0;
    while (num--) {
        random();//获取表达式
        double ans;
        std::cin >> ans;

        if (fabs(calc() - ans) <= 1e-2){//可能会出现精度误差由于除法的存在
            std::cout << "回答正确!\n";
            ok++;
        }
        else {
            std::cout << "回答错误!\n正确答案为:" << calc() << "\n";
        }
    }
    std::cout << "本次一共有算术式:" << sum << "\n";
    std::cout << "你一共答对了:" << ok << "题\n";
    printf("你的正确率为:%.2lf", ok*1.0 / sum);
    return 0;
}

运算效果:

 

进阶版,每个表达式不一定只有一个运算符号,

首先还是随机生成数据方面,可以发现这样的表达式一定是一个数字一个符号这样重复,最后再加上一个数字构成的,于是我们可以随机生成1-4之间的数,然后循环,来表达出这样的式子

  

std::string frandom() {//随机生成数字,一个式子可以多个运算符
    srand(time(0));//时间种子
    int p = rand() % 3 + 1;//可以自己设置运算符的数量
    std::string f;
    for (int i = 1; i <= p; i++) {
        a = rand() % 100+1;//生成0到100之间的随机数
        t = rand() % 4;//生成运算符下标
        f += std::to_string(a);
        f += opp[t];
    }
    b = rand() % 100 + 1;//由于分母不能为0,所以得生成1-100;
    f += std::to_string(b);
    return f;
}

其次就是计算方面,需要一点数据结构的知识,来进行判断一下优先级大小,然后再利用栈存储数字来计算

std::stack<double> num;
std::stack<char> op;
//优先级表
std::unordered_map<char, int> pr{ {'+', 1}, {'-', 1}, {'*',2}, {'/', 2} };

void eval() { // 操作
    int a = num.top();//第二个操作数
    num.pop(); // 左节点 
    int b = num.top();//第一个操作数
    num.pop();
    char p = op.top();//运算符
    op.pop();
    int r = 0;//结果 
    //计算结果
    if (p == '+') r = b + a;
    if (p == '-') r = b - a;
    if (p == '*') r = b * a;
    if (p == '/') r = b / a;
    num.push(r);//结果入栈
}



double calc(std::string s) {
    for (int i = 0; i < s.size(); i++) {
        if (isdigit(s[i])) {
            int x = 0, j = i;//计算数字
            while (j < s.size() && isdigit(s[j])) {
                x = x * 10 + s[j++] - '0'; // 迭代计算压入的数字 
            }
            num.push(x);//数字入栈
            i = j - 1;
        }
        //左括号无优先级,直接入栈
        else if (s[i] == '(') {
            op.push(s[i]);
        }
        //括号特殊,遇到左括号直接入栈,遇到右括号计算括号里面的
        else if (s[i] == ')') {
            while (op.top() != '(')//一直计算到左括号
                eval();
            op.pop();//左括号出栈
        }
        else {
            while (op.size() && pr[op.top()] >= pr[s[i]])//待入栈运算符优先级低,则先计算 
                eval();
            op.push(s[i]);//操作符入栈
        }
    }
    while (op.size()) eval();//剩余的进行计算
    return num.top();//输出结果

}

 

 

完整代码

#include<iostream>
#include<stack>
#include<unordered_map>
#include<string>
char opp[] = { '+','-','*','/' };//运算符号
int a, t, b;

std::stack<double> num;
std::stack<char> op;
//优先级表
std::unordered_map<char, int> pr{ {'+', 1}, {'-', 1}, {'*',2}, {'/', 2} };


std::string frandom() {//随机生成数字,一个式子可以多个运算符
    srand(time(0));//时间种子
    int p = rand() % 3 + 1;//可以自己设置运算符的数量
    std::string f;
    for (int i = 1; i <= p; i++) {
        a = rand() % 100+1;//生成0到100之间的随机数
        t = rand() % 4;//生成运算符下标
        f += std::to_string(a);
        f += opp[t];
    }
    b = rand() % 100 + 1;//由于分母不能为0,所以得生成1-100;
    f += std::to_string(b);
    return f;
}

void eval() { // 操作
    int a = num.top();//第二个操作数
    num.pop(); // 左节点 
    int b = num.top();//第一个操作数
    num.pop();
    char p = op.top();//运算符
    op.pop();
    int r = 0;//结果 
    //计算结果
    if (p == '+') r = b + a;
    if (p == '-') r = b - a;
    if (p == '*') r = b * a;
    if (p == '/') r = b / a;
    num.push(r);//结果入栈
}



double calc(std::string s) {
    for (int i = 0; i < s.size(); i++) {
        if (isdigit(s[i])) {
            int x = 0, j = i;//计算数字
            while (j < s.size() && isdigit(s[j])) {
                x = x * 10 + s[j++] - '0'; // 迭代计算压入的数字 
            }
            num.push(x);//数字入栈
            i = j - 1;
        }
        //左括号无优先级,直接入栈
        else if (s[i] == '(') {
            op.push(s[i]);
        }
        //括号特殊,遇到左括号直接入栈,遇到右括号计算括号里面的
        else if (s[i] == ')') {
            while (op.top() != '(')//一直计算到左括号
                eval();
            op.pop();//左括号出栈
        }
        else {
            while (op.size() && pr[op.top()] >= pr[s[i]])//待入栈运算符优先级低,则先计算 
                eval();
            op.push(s[i]);//操作符入栈
        }
    }
    while (op.size()) eval();//剩余的进行计算
    return num.top();//输出结果

}

int main() {
    int num; 
    std::cout << "请输入你要挑战的算术式的数量:\n";
    std::cin >> num;
    int sum = num;
    int ok = 0;
    while (num--) {
        std::string f=frandom();//获取表达式
        std::cout << f << "=\n";
        double ans;
        std::cin >> ans;

        if (ans==calc(f)){//这里为了定义除法只保留整数位
            std::cout << "回答正确!\n";
            ok++;
        }
        else {
            std::cout << "回答错误!\n正确答案为:" << calc(f) << "\n";
        }
    }
    std::cout << "本次一共有算术式:" << sum << "\n";
    std::cout << "你一共答对了:" << ok << "题\n";
    printf("你的正确率为:%.2lf", ok*1.0 / sum);
    return 0;
}
View Code

 

运算效果

 

posted @ 2024-04-16 13:25  yzy001  阅读(8)  评论(0编辑  收藏  举报