求函数值域

· · 学习·文化课

#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;
}