生成随机学生数学问题

Generate random pupil math problems

本文关键字:问题 随机      更新时间:2023-10-16

我尝试使用c ++为孩子们构建一个程序来练习数学。问题应包括加法、减法、乘法和除法。这10个问题是随机生成的。此外,随机生成问题的数字。但是,必须确保问题和结果都不超过两位数。问题和结果应大于或等于零。除数不能为零。

我的实施被遵循。

while(prob_cout < 10){
int op = rand() % 4; // range 0-3 to match a operation
int answer, userGuess;
if (op == 0) { // addition
int number1 = rand() % 100; // problem no langer than two digits 
int number2 = rand() % 100;  // range 0-99 
answer = number1 + number2;
if (answer >= 0 && answer < 100) { // valid problem: result also no more than two digits
prob_cout++;
cout << number1 << " + " << number2 << " = ";
cin >> userGuess;
// record problem info
prob_record.push_back(number1);
prob_record.push_back(op);
prob_record.push_back(number2);
prob_record.push_back(answer);
prob_record.push_back(userGuess);
// check answer
if (answer == userGuess)
user_scores += 10;
else
continue;
}
else
continue;
}
else if(op == 1) { // subtraction
int number1 = rand() % 100; // problem no langer than two digits 
int number2 = rand() % 100;  // range 0-99 
answer = number1 - number2;
if (answer >= 0 && answer < 100) { // valid problem: result also no more than two digits
prob_cout++;
cout << number1 << " - " << number2 << " = ";
cin >> userGuess;
// record problem info
prob_record.push_back(number1);
prob_record.push_back(op);
prob_record.push_back(number2);
prob_record.push_back(answer);
prob_record.push_back(userGuess);
if (answer == userGuess)
user_scores += 10;
else
continue;
}
else
continue;
}
else if (op == 2) { // multiplication
int number1 = rand() % 20; 
int number2 = rand() % 20;   
answer = number1 * number2;
if (answer >= 0 && answer < 100) { // valid problem: result also no more than two digits
prob_cout++;
cout << number1 << " * " << number2 << " = ";
cin >> userGuess;
// record problem info
prob_record.push_back(number1);
prob_record.push_back(op);
prob_record.push_back(number2);
prob_record.push_back(answer);
prob_record.push_back(userGuess);
// check answer
if (answer == userGuess)
user_scores += 10;
else
continue;
}
else
continue;
}
else if (op == 3) { //dividion
int number1 = rand() % 100; 
int number2 = rand() % 50; 
answer = number1 / number2;
if (answer >= 0 && answer < 100 && number1 > number2) { // valid problem: result also no more than two digits
prob_cout++;
cout << number1 << " / " << number2 << " = ";
cin >> userGuess;
// record problem info
prob_record.push_back(number1);
prob_record.push_back(op);
prob_record.push_back(number2);
prob_record.push_back(answer);
prob_record.push_back(userGuess);
// check answer
if (answer == userGuess)
user_scores += 10;
else
continue;
}
else
continue;
}
}

但。我发现这种方法不能确保这四种操作的同等可能性。加法和减法不仅仅是乘法和除法!

有人有更好的主意吗?

我很想找到一种数学方法来确保选择的值在可接受的范围内。

像这样:

#include <iostream>
#include <random>
#include <string>
int random_number(int from, int to)
{
thread_local static std::mt19937 mt{std::random_device{}()};
return std::uniform_int_distribution<int>{from, to}(mt);
}
int main()
{
std::string const ops = "+-*/";
for(auto n = 0; n < 10; ++n)
{
int lhs;
int rhs;
auto op = ops[random_number(0, 3)];
switch(op)
{
case '+':
lhs = random_number(0, 99);
rhs = random_number(0, 99 - lhs);
if(random_number(0, 1))
std::swap(lhs, rhs);
break;
case '-':
lhs = random_number(0, 99);
rhs = random_number(0, lhs);
break;
case '*':
lhs = random_number(1, 99);
rhs = random_number(0, 99 / lhs);
if(random_number(0, 1))
std::swap(lhs, rhs);
break;
case '/':
rhs = random_number(1, 10);
lhs = rhs * random_number(0, 10);
break;
}
std::cout << (n < 9 ? " ":"") << (n + 1);
std::cout << ": " << (lhs < 10 ? " ":"") << lhs;
std::cout << " " << op;
std::cout << " " << (rhs < 10 ? " ":"") << rhs;
std::cout << " = " << 'n';
}
}

示例输出:

1:  1 * 27 = 
2: 12 /  2 = 
3:  1 + 94 = 
4: 87 - 63 = 
5:  1 -  1 = 
6:  9 *  6 = 
7: 39 - 39 = 
8: 47 + 33 = 
9: 21 /  3 = 
10: 49 + 48 = 

问题要求,如if(answer >= 0 && answer < 100),比乘除法更有可能通过加减法来满足。这就是为什么后者的更多问题被拒绝的原因。

如果您希望这些操作的份额几乎相等,一个简单的解决方法是不要在每个循环中再次选择运算符,而是保留相同的运算符并重试,直到同一运算符出现可接受的问题。

为此,首先将运算符初始化为某个值,例如 -1,仅在这种情况下添加选择新运算符。另一方面,当已选择的运算符的问题被拒绝时,您将不会选择新的运算符。只有在生成并接受问题时,您才会设置op = -1,恰好在您设置的每个位置附近prob_cout++;

总体结构为:

int op = -1;
while(prob_cout < 10){
if(op == -1) op = rand() % 4; // <-- dont select a new operation when op already selected
int answer, userGuess;
if (op == 0) { // addition
// generate addition problem
if (answer >= 0 && answer < 100) { // valid problem                   
prob_cout++;
op = -1; // <----- so that next iteration an new operator is randomly selected.
// Place op = -1 near each prob_cout++ statement in your initial code.

请注意,这是一个建议,以(快速)解决平衡不同运营商的频率问题。但是,我认为从代码质量的角度来看,您的代码还有改进的余地,因为它有很多可以以某种方式分解的重复操作。但这是另一个话题。