求函数值域
songyuteng · · 学习·文化课
#include <iostream>
#include <cmath>
#include <string>
#include <chrono>
#include <iomanip>
#include <algorithm>
using namespace std;
using namespace chrono;
// 显示函数类型对应表
void printFunctionTypes() {
cout << "函数类型对应表:" << endl;
cout << "1: 一次函数 (y = kx + b)" << endl;
cout << "2: 二次函数 (y = ax2 + bx + c)" << endl;
cout << "3: 三次函数 (y = ax3 + bx2 + cx + d)" << endl;
cout << "4: 绝对值函数 (y = |kx + b| + c)" << endl;
cout << "5: 幂函数 (y = x^a)" << endl;
cout << "6: 指数函数 (y = a^x + b)" << endl;
cout << "7: 对数函数 (y = log_a(x) + b)" << endl;
cout << "8: 对勾函数 (y = x + a/x)" << endl;
cout << "9: 反比例函数 (y = k/x + b)" << endl;
}
// 计算函数在x处的值
double calculateFunction(int funcType, double params[], double x) {
switch(funcType) {
case 1:
return params[0] * x + params[1]; // 一次函数
case 2:
return params[0] * x * x + params[1] * x + params[2]; // 二次函数
case 3:
return params[0] * x * x * x + params[1] * x * x + params[2] * x + params[3]; // 三次函数
case 4:
return fabs(params[0] * x + params[1]) + params[2]; // 绝对值函数
case 5:
return pow(x, params[0]); // 幂函数
case 6:
return pow(params[0], x) + params[1]; // 指数函数
case 7:
return log(x) / log(params[0]) + params[1]; // 对数函数
case 8:
return x + params[0] / x; // 对勾函数
case 9:
return params[0] / x + params[1]; // 反比例函数
default:
return 0;
}
}
// 检查x是否在区间内
bool isInInterval(double x, double interval[]) {
return x >= interval[0] && x <= interval[1];
}
// 根据函数类型、参数和区间计算值域
string getIntervalRange(int funcType, double params[], double interval[]) {
double a = interval[0];
double b = interval[1];
double minVal, maxVal;
bool first = true;
// 特殊点集合(端点和可能的极值点)
vector<double> criticalPoints;
criticalPoints.push_back(a);
criticalPoints.push_back(b);
// 根据函数类型添加可能的极值点
switch(funcType) {
case 1: {
// 一次函数 - 单调,只需端点
break;
}
case 2: {
// 二次函数 - 顶点为极值点
double a_coeff = params[0];
double b_coeff = params[1];
if (a_coeff != 0) {
double vertexX = -b_coeff / (2 * a_coeff);
if (isInInterval(vertexX, interval)) {
criticalPoints.push_back(vertexX);
}
}
break;
}
case 3: {
// 三次函数 - 可能有两个极值点
double a_coeff = params[0];
double b_coeff = params[1];
double c_coeff = params[2];
if (a_coeff != 0) {
double discriminant = b_coeff * b_coeff - 3 * a_coeff * c_coeff;
if (discriminant > 0) {
double sqrtD = sqrt(discriminant);
double x1 = (-b_coeff - sqrtD) / (3 * a_coeff);
double x2 = (-b_coeff + sqrtD) / (3 * a_coeff);
if (isInInterval(x1, interval)) {
criticalPoints.push_back(x1);
}
if (isInInterval(x2, interval)) {
criticalPoints.push_back(x2);
}
}
}
break;
}
case 4: {
// 绝对值函数 - 转折点
double k = params[0];
double b_coeff = params[1];
if (k != 0) {
double turningPoint = -b_coeff / k;
if (isInInterval(turningPoint, interval)) {
criticalPoints.push_back(turningPoint);
}
}
break;
}
case 5: {
// 幂函数 - 可能在0点有极值
double exponent = params[0];
if (exponent != 1 && isInInterval(0, interval)) {
criticalPoints.push_back(0);
}
break;
}
case 8: {
// 对勾函数 - 极值点
double coeff = params[0];
if (coeff > 0) {
double x1 = sqrt(coeff);
double x2 = -sqrt(coeff);
if (isInInterval(x1, interval)) {
criticalPoints.push_back(x1);
}
if (isInInterval(x2, interval)) {
criticalPoints.push_back(x2);
}
}
break;
}
case 9: {
// 反比例函数 - 渐近线x=0
if (a < 0 && b > 0) {
// 区间包含奇点,需要分开处理
// 这里简化处理,只检查端点
break;
}
break;
}
}
// 计算所有特殊点的函数值,找到最大值和最小值
for (double x : criticalPoints) {
// 检查函数定义域
if ((funcType == 7 && x <= 0) || // 对数函数定义域
(funcType == 8 && x == 0) || // 对勾函数x不能为0
(funcType == 9 && x == 0)) { // 反比例函数x不能为0
continue;
}
double y = calculateFunction(funcType, params, x);
if (first) {
minVal = y;
maxVal = y;
first = false;
} else {
if (y < minVal) minVal = y;
if (y > maxVal) maxVal = y;
}
}
// 如果没有有效点(定义域问题)
if (first) {
return "在指定区间内函数无定义";
}
// 处理反比例函数特殊情况(区间包含奇点)
if (funcType == 9 && params[0] != 0 && a < 0 && b > 0) {
return "(-∞, +∞)"; // 区间包含奇点时,反比例函数值域为全体实数
}
// 格式化输出
stringstream ss;
ss << fixed << setprecision(4);
ss << "[" << minVal << ", " << maxVal << "]";
return ss.str();
}
// 计算整个定义域上的值域
string getGlobalRange(int funcType, double params[]) {
switch(funcType) {
case 1: {
double k = params[0], b = params[1];
if (k == 0) {
return "{" + to_string(b) + "}";
} else {
return "(-∞, +∞)";
}
}
case 2: {
double a = params[0], b = params[1], c = params[2];
if (a == 0) {
double tempParams[2] = {b, c};
return getGlobalRange(1, tempParams);
}
double vertexY = (4*a*c - b*b) / (4*a);
stringstream ss;
ss << fixed << setprecision(4) << vertexY;
if (a > 0) {
return "[" + ss.str() + ", +∞)";
} else {
return "(-∞, " + ss.str() + "]";
}
}
case 3:
return "(-∞, +∞)";
case 4: {
double k = params[0], b = params[1], c = params[2];
if (k == 0) {
return "{" + to_string(fabs(b) + c) + "}";
} else {
return "[" + to_string(c) + ", +∞)";
}
}
case 5: {
double a = params[0];
if (a > 0) {
return "[0, +∞)";
} else if (a < 0) {
return "(0, +∞)";
} else {
return "{1}";
}
}
case 6: {
double a = params[0], b = params[1];
if (a <= 0 || a == 1) {
return "无效的底数,指数函数底数需满足a > 0且a ≠ 1";
}
return "(" + to_string(b) + ", +∞)";
}
case 7: {
double a = params[0], b = params[1];
if (a <= 0 || a == 1) {
return "无效的底数,对数函数底数需满足a > 0且a ≠ 1";
}
return "(-∞, +∞)";
}
case 8: {
double a = params[0];
if (a > 0) {
double sqrtA = sqrt(a);
stringstream ss;
ss << fixed << setprecision(4) << -2*sqrtA << ", " << 2*sqrtA;
return "(-∞, " + to_string(-2*sqrtA) + "] ∪ [" + to_string(2*sqrtA) + ", +∞)";
} else if (a < 0) {
return "(-∞, +∞)";
} else {
return "(-∞, +∞)";
}
}
case 9: {
double k = params[0], b = params[1];
if (k == 0) {
return "{" + to_string(b) + "}";
}
return "(-∞, " + to_string(b) + ") ∪ (" + to_string(b) + ", +∞)";
}
default:
return "无效的函数类型";
}
}
int main() {
auto startTime = high_resolution_clock::now();
// 显示函数类型
printFunctionTypes();
// 获取用户输入的函数类型
int funcType;
cout << "\n请输入函数类型的序号 (1-9): ";
cin >> funcType;
if (cin.fail() || funcType < 1 || funcType > 9) {
cout << "请输入1-9之间的有效数字" << endl;
return 1;
}
// 获取区间
cout<<"\n请问是否求区间? 1.是 0.否"<<endl;
int opp;
cin>>opp;
double interval[2];
if(opp==1) {
cout << "请输入x的取值区间 [a, b]" << endl;
cout << "a = ";
cin >> interval[0];
cout << "b = ";
cin >> interval[1];
if (cin.fail() || interval[0] > interval[1]) {
cout << "请输入有效的区间 (a ≤ b)" << endl;
return 1;
}
}
// 根据函数类型获取参数
double params[4]; // 最多需要4个参数
bool inputValid = true;
try {
if (funcType == 1) {
// 一次函数:k, b
cout << "请输入k的值: ";
cin >> params[0];
cout << "请输入b的值: ";
cin >> params[1];
} else if (funcType == 2) {
// 二次函数:a, b, c
cout << "请输入a的值: ";
cin >> params[0];
cout << "请输入b的值: ";
cin >> params[1];
cout << "请输入c的值: ";
cin >> params[2];
} else if (funcType == 3) {
// 三次函数:a, b, c, d
cout << "请输入a的值: ";
cin >> params[0];
cout << "请输入b的值: ";
cin >> params[1];
cout << "请输入c的值: ";
cin >> params[2];
cout << "请输入d的值: ";
cin >> params[3];
} else if (funcType == 4) {
// 绝对值函数:k, b, c
cout << "请输入k的值: ";
cin >> params[0];
cout << "请输入b的值: ";
cin >> params[1];
cout << "请输入c的值: ";
cin >> params[2];
} else if (funcType == 5) {
// 幂函数:a
cout << "请输入指数a的值: ";
cin >> params[0];
} else if (funcType == 6) {
// 指数函数:a, b
cout << "请输入底数a的值 (a > 0且a ≠ 1): ";
cin >> params[0];
cout << "请输入b的值: ";
cin >> params[1];
} else if (funcType == 7) {
// 对数函数:a, b
cout << "请输入底数a的值 (a > 0且a ≠ 1): ";
cin >> params[0];
cout << "请输入b的值: ";
cin >> params[1];
// 检查对数函数区间有效性
if (interval[0] <= 0) {
cout << "警告:对数函数定义域为x > 0,区间将自动调整为(" << max(interval[0], 1e-9) << ", " << interval[1] << "]" << endl;
interval[0] = max(interval[0], 1e-9);
}
} else if (funcType == 8) {
// 对勾函数:a
cout << "请输入a的值: ";
cin >> params[0];
// 检查对勾函数区间有效性
if (interval[0] <= 0 && interval[1] >= 0) {
cout << "警告:对勾函数在x=0处无定义,区间包含0点可能导致结果不准确" << endl;
}
} else if (funcType == 9) {
// 反比例函数:k, b
cout << "请输入k的值 (k ≠ 0): ";
cin >> params[0];
cout << "请输入b的值: ";
cin >> params[1];
// 检查反比例函数区间有效性
if (interval[0] <= 0 && interval[1] >= 0) {
cout << "警告:反比例函数在x=0处无定义,区间包含0点" << endl;
}
}
if (cin.fail()) {
printf("输入无效\n");
}
} catch (...) {
cout << "请输入有效的数字参数" << endl;
return 1;
}
// 计算并显示值域
if(opp==0){
string globalResult = getGlobalRange(funcType, params);
cout << "\n函数的全局值域为: " << globalResult << endl;
}
else{
string intervalResult = getIntervalRange(funcType, params, interval);
cout << "函数在区间[" << interval[0] << ", " << interval[1] << "]内的值域为: " << intervalResult << endl;
}
return 0;
}