C++課設:簡易科學計算器(支持+-*/、sin、cos、tan、log等科學函數)

名人說:路漫漫其修遠兮,吾將上下而求索。—— 屈原《離騷》
創作者:Code_流蘇(CSDN)(一個喜歡古詩詞和編程的Coder😊)
專欄介紹:《編程項目實戰》

目錄

    • 一、項目概覽與設計理念
      • 1. 功能特色
      • 2. 技術架構
    • 二、核心算法深度解析
      • 1. 詞法分析(Tokenization)
      • 2. 中綴轉后綴(調度場算法)
      • 3. 后綴表達式求值
    • 三、代碼架構與類設計
      • 1. Calculator類的整體結構
      • 2. 函數注冊機制
    • 四、特色功能詳解
      • 1. 角度與弧度的智能處理
      • 2. 錯誤處理與用戶體驗
      • 3. 交互式演示功能
    • 五、實際運行演示
      • 1. 基礎運算示例
      • 2. 科學計算示例
      • 3. 復雜表達式示例
    • 六、完整源代碼
    • 七、總結與擴展思考

在編程學習的道路上,表達式求值一直是一個經典而重要的問題。今天我們將深入探討如何用C++從零開始構建一個功能完整的科學計算器,它不僅支持基礎的四則運算,還能處理復雜的科學函數計算。這個項目將帶你領略詞法分析調度場算法后綴表達式求值等核心計算機科學概念的魅力。

一、項目概覽與設計理念

1. 功能特色

這個計算器具備以下核心功能:

  • 基礎運算:加減乘除、冪運算(支持^**兩種語法)
  • 科學函數:三角函數、對數函數、開方、絕對值等
  • 角度支持:同時支持弧度和角度計算(sin vs sind
  • 智能解析:完整的表達式詞法分析和語法解析
  • 錯誤處理:友好的錯誤提示和異常處理

2. 技術架構

整個計算器采用三階段處理流程

輸入表達式 → 詞法分析 → 中綴轉后綴 → 后綴求值 → 輸出結果

在這里插入圖片描述

這種設計遵循了編譯原理的經典思想,將復雜問題分解為獨立的處理階段,每個階段都有明確的職責。

二、核心算法深度解析

1. 詞法分析(Tokenization)

詞法分析是整個計算過程的第一步,它將輸入的字符串分解為有意義的詞法單元(Token)。

enum TokenType {NUMBER,      // 數字OPERATOR,    // 操作符FUNCTION,    // 函數LEFT_PAREN,  // 左括號RIGHT_PAREN  // 右括號
};struct Token {TokenType type;string value;double numValue;
};

詞法分析器會識別以下模式:

  • 數字識別:支持整數和浮點數
  • 操作符識別:包括特殊的雙字符操作符**
  • 函數識別:動態匹配預定義的函數名
  • 括號匹配:正確處理嵌套括號

2. 中綴轉后綴(調度場算法)

這里使用了著名的調度場算法(Shunting-yard Algorithm),這是計算機科學家Edsger Dijkstra發明的經典算法。

為什么要轉換為后綴表達式?

  • 消除了操作符優先級的歧義
  • 無需括號就能明確表達計算順序
  • 求值過程更加簡單高效
vector<Token> infixToPostfix(const vector<Token>& tokens) {vector<Token> output;stack<Token> operators;for (const Token& token : tokens) {switch (token.type) {case NUMBER:output.push_back(token);break;case OPERATOR:// 處理操作符優先級和結合性while (!operators.empty() && shouldPopOperator(token, operators.top())) {output.push_back(operators.top());operators.pop();}operators.push(token);break;// ... 其他情況處理}}return output;
}

3. 后綴表達式求值

后綴表達式的求值過程非常直觀:遇到數字壓棧,遇到操作符彈出操作數計算

double evaluatePostfix(const vector<Token>& postfix) {stack<double> values;for (const Token& token : postfix) {if (token.type == NUMBER) {values.push(token.numValue);} else if (token.type == OPERATOR) {double b = values.top(); values.pop();double a = values.top(); values.pop();values.push(calculate(a, token.value, b));}// ... 函數處理}return values.top();
}

三、代碼架構與類設計

1. Calculator類的整體結構

class Calculator {
private:map<string, int> operatorPrecedence;        // 操作符優先級map<string, bool> rightAssociative;        // 右結合性標記map<string, double (*)(double)> functions; // 函數指針映射public:Calculator() {initOperators();initFunctions();}double calculate(const string& expression);void showInfixToPostfix(const string& expression);void showSupportedFunctions();
};

這種設計的優勢:

  • 封裝性好:所有計算邏輯都在類內部
  • 可擴展性強:新增函數只需修改初始化代碼
  • 配置化:操作符優先級和函數都通過映射表管理

2. 函數注冊機制

計算器使用函數指針映射實現動態函數調用:

void initFunctions() {// 基礎數學函數functions["sin"] = sin;functions["cos"] = cos;functions["sqrt"] = sqrt;// 角度版本的三角函數functions["sind"] = sind;functions["cosd"] = cosd;functions["tand"] = tand;
}

這種設計使得添加新函數變得極其簡單,只需要定義函數并注冊到映射表中即可。

四、特色功能詳解

1. 角度與弧度的智能處理

這個計算器的一大亮點是同時支持角度和弧度計算

// 弧度版本(標準數學函數)
sin(1.57)  // ≈ 1.0// 角度版本(添加d后綴)
sind(90)   // = 1.0

實現原理:

static double sind(double deg) {return sin(degToRad(deg));
}static double degToRad(double deg) {return deg * 3.14159265358979323846 / 180.0;
}

2. 錯誤處理與用戶體驗

代碼中實現了多層次的錯誤處理:

try {double result = calc.calculate(input);cout << "結果: " << fixed << setprecision(6) << result << endl;
} catch (const exception& e) {cout << "錯誤: " << e.what() << endl;
}

常見錯誤類型:

  • 除零錯誤if (b == 0) throw runtime_error("除零錯誤");
  • 語法錯誤:括號不匹配、操作符缺少操作數
  • 函數錯誤:未知函數名、參數缺失

3. 交互式演示功能

計算器提供了豐富的演示功能:

// 輸入 "demo" 查看處理過程
calc.showInfixToPostfix("3 + 4 * 2 / ( 1 - 5 ) ^ 2");// 輸出:
// 原始表達式: 3 + 4 * 2 / ( 1 - 5 ) ^ 2
// 詞法分析結果: 3 4 2 * 1 5 - 2 ^ / +
// 后綴表達式: 3 4 2 * 1 5 - 2 ^ / +

五、實際運行演示

1. 基礎運算示例

請輸入表達式: 3 + 4 * 2
結果: 11.000000請輸入表達式: 2 ^ 3 * 4
結果: 32.000000請輸入表達式: sqrt(16) + log10(100)
結果: 6.000000

在這里插入圖片描述

2. 科學計算示例

請輸入表達式: sind(30) + cosd(60)
結果: 1.000000請輸入表達式: log(exp(5))
結果: 5.000000

在這里插入圖片描述

3. 復雜表達式示例

請輸入表達式: sin(deg2rad(45)) * sqrt(2)
結果: 1.000000請輸入表達式: (sind(30) + cosd(60)) * log10(100)
結果: 2.000000

在這里插入圖片描述

六、完整源代碼

以下是完整的計算器實現代碼:

#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <cmath>
#include <cctype>
#include <sstream>
#include <map>
#include <iomanip>
#include <stdexcept>
#include <cstdlib>using namespace std;// 枚舉類型定義操作符和函數類型
enum TokenType {NUMBER,OPERATOR,FUNCTION,LEFT_PAREN,RIGHT_PAREN
};// 表示一個詞法單元
struct Token {TokenType type;string value;double numValue;Token(TokenType t, const string& v, double n = 0) : type(t), value(v), numValue(n) {}
};class Calculator {
private:map<string, int> operatorPrecedence;map<string, bool> rightAssociative;map<string, double (*)(double)> functions;void initOperators() {// 設置操作符優先級operatorPrecedence["+"] = 1;operatorPrecedence["-"] = 1;operatorPrecedence["*"] = 2;operatorPrecedence["/"] = 2;operatorPrecedence["^"] = 3;operatorPrecedence["**"] = 3;// 設置右結合性(只有冪運算是右結合的)rightAssociative["^"] = true;rightAssociative["**"] = true;}// 角度轉弧度輔助函數static double degToRad(double deg) {return deg * 3.14159265358979323846 / 180.0;}static double radToDeg(double rad) {return rad * 180.0 / 3.14159265358979323846;}// 角度版本的三角函數static double sind(double deg) {return sin(degToRad(deg));}static double cosd(double deg) {return cos(degToRad(deg));}static double tand(double deg) {return tan(degToRad(deg));}// 包裝函數來避免直接使用庫函數指針static double log_wrapper(double x) {return log(x);}static double log10_wrapper(double x) {return log10(x);}static double exp_wrapper(double x) {return exp(x);}static double sqrt_wrapper(double x) {return sqrt(x);}static double abs_wrapper(double x) {return fabs(x);}static double sin_wrapper(double x) {return sin(x);}static double cos_wrapper(double x) {return cos(x);}static double tan_wrapper(double x) {return tan(x);}static double ceil_wrapper(double x) {return ceil(x);}static double floor_wrapper(double x) {return floor(x);}void initFunctions() {// 注冊科學計算函數(使用包裝函數)functions["sin"] = sin_wrapper;functions["cos"] = cos_wrapper;functions["tan"] = tan_wrapper;// 注冊角度版本的三角函數functions["sind"] = sind;functions["cosd"] = cosd;functions["tand"] = tand;// 其他數學函數(使用包裝函數)functions["sqrt"] = sqrt_wrapper;functions["log"] = log_wrapper;functions["log10"] = log10_wrapper;  // 重點修復functions["exp"] = exp_wrapper;functions["abs"] = abs_wrapper;functions["ceil"] = ceil_wrapper;functions["floor"] = floor_wrapper;// 角度轉換函數functions["deg2rad"] = degToRad;functions["rad2deg"] = radToDeg;}// 詞法分析器vector<Token> tokenize(const string& expression) {vector<Token> tokens;string current = "";for (size_t i = 0; i < expression.length(); i++) {char c = expression[i];if (isspace(c)) {continue;}if (isdigit(c) || c == '.') {current += c;} else {// 如果當前有數字,先處理數字if (!current.empty()) {double num = atof(current.c_str());tokens.push_back(Token(NUMBER, current, num));current = "";}// 處理操作符和特殊字符if (c == '+' || c == '-' || c == '*' || c == '/' || c == '^') {// 檢查是否是冪運算符 **if (c == '*' && i + 1 < expression.length() && expression[i + 1] == '*') {tokens.push_back(Token(OPERATOR, "**"));i++; // 跳過下一個 *} else {string op(1, c);tokens.push_back(Token(OPERATOR, op));}} else if (c == '(') {tokens.push_back(Token(LEFT_PAREN, "("));} else if (c == ')') {tokens.push_back(Token(RIGHT_PAREN, ")"));} else if (isalpha(c)) {// 處理函數名(支持包含數字的函數名如log10)string funcName = "";while (i < expression.length() && (isalpha(expression[i]) || isdigit(expression[i]))) {funcName += expression[i];i++;}i--; // 回退一位,因為for循環會自增if (functions.find(funcName) != functions.end()) {tokens.push_back(Token(FUNCTION, funcName));} else {cout << "未知函數: " << funcName << endl;return vector<Token>(); // 返回空向量表示錯誤}} else {// 遇到不支持的字符,給出相應提示if (c < 0 || c > 127) {cout << "警告: 忽略特殊字符(可能是°符號)" << endl;cout << "提示: 請使用角度函數 sind(), cosd(), tand() 代替°符號" << endl;} else {cout << "警告: 忽略不支持的字符 '" << c << "'" << endl;}}}}// 處理最后的數字if (!current.empty()) {double num = atof(current.c_str());tokens.push_back(Token(NUMBER, current, num));}return tokens;}// 中綴轉后綴(調度場算法)vector<Token> infixToPostfix(const vector<Token>& tokens) {vector<Token> output;stack<Token> operators;for (size_t i = 0; i < tokens.size(); i++) {const Token& token = tokens[i];switch (token.type) {case NUMBER:output.push_back(token);break;case FUNCTION:operators.push(token);break;case OPERATOR: {while (!operators.empty() && operators.top().type != LEFT_PAREN &&((operators.top().type == FUNCTION) ||(operators.top().type == OPERATOR &&((operatorPrecedence[operators.top().value] > operatorPrecedence[token.value]) ||(operatorPrecedence[operators.top().value] == operatorPrecedence[token.value] &&rightAssociative.find(token.value) == rightAssociative.end()))))) {output.push_back(operators.top());operators.pop();}operators.push(token);break;}case LEFT_PAREN:operators.push(token);break;case RIGHT_PAREN:while (!operators.empty() && operators.top().type != LEFT_PAREN) {output.push_back(operators.top());operators.pop();}if (!operators.empty() && operators.top().type == LEFT_PAREN) {operators.pop(); // 移除左括號}// 如果棧頂是函數,也要彈出if (!operators.empty() && operators.top().type == FUNCTION) {output.push_back(operators.top());operators.pop();}break;}}// 彈出剩余的操作符while (!operators.empty()) {output.push_back(operators.top());operators.pop();}return output;}// 計算后綴表達式double evaluatePostfix(const vector<Token>& postfix) {stack<double> values;for (size_t i = 0; i < postfix.size(); i++) {const Token& token = postfix[i];switch (token.type) {case NUMBER:values.push(token.numValue);break;case OPERATOR: {if (values.size() < 2) {throw runtime_error("表達式錯誤:操作符缺少操作數");}double b = values.top(); values.pop();double a = values.top(); values.pop();double result = 0;if (token.value == "+") {result = a + b;} else if (token.value == "-") {result = a - b;} else if (token.value == "*") {result = a * b;} else if (token.value == "/") {if (b == 0) {throw runtime_error("除零錯誤");}result = a / b;} else if (token.value == "^" || token.value == "**") {result = pow(a, b);}values.push(result);break;}case FUNCTION: {if (values.empty()) {throw runtime_error("表達式錯誤:函數缺少參數");}double arg = values.top(); values.pop();// 添加調試信息cout << "正在計算函數: " << token.value << "(" << arg << ")" << endl;if (functions.find(token.value) == functions.end()) {throw runtime_error("未知函數: " + token.value);}double result = functions[token.value](arg);cout << "結果: " << result << endl;values.push(result);break;}default:break;}}if (values.size() != 1) {throw runtime_error("表達式錯誤");}return values.top();}public:Calculator() {initOperators();initFunctions();}// 主要的計算函數double calculate(const string& expression) {// 1. 詞法分析vector<Token> tokens = tokenize(expression);if (tokens.empty()) {throw runtime_error("無效的表達式");}// 調試:顯示詞法分析結果cout << "詞法分析結果: ";for (size_t i = 0; i < tokens.size(); i++) {cout << "[" << tokens[i].value << "] ";}cout << endl;// 2. 中綴轉后綴vector<Token> postfix = infixToPostfix(tokens);// 3. 計算后綴表達式return evaluatePostfix(postfix);}// 顯示中綴轉后綴的過程void showInfixToPostfix(const string& expression) {cout << "原始表達式: " << expression << endl;vector<Token> tokens = tokenize(expression);cout << "詞法分析結果: ";for (size_t i = 0; i < tokens.size(); i++) {cout << tokens[i].value << " ";}cout << endl;vector<Token> postfix = infixToPostfix(tokens);cout << "后綴表達式: ";for (size_t i = 0; i < postfix.size(); i++) {cout << postfix[i].value << " ";}cout << endl;}// 顯示支持的函數列表void showSupportedFunctions() {cout << "\n支持的科學計算函數:" << endl;cout << "=== 三角函數(弧度) ===" << endl;cout << "sin(x)   - 正弦函數(x為弧度)" << endl;cout << "cos(x)   - 余弦函數(x為弧度)" << endl;cout << "tan(x)   - 正切函數(x為弧度)" << endl;cout << "\n=== 三角函數(角度) ===" << endl;cout << "sind(x)  - 正弦函數(x為角度)" << endl;cout << "cosd(x)  - 余弦函數(x為角度)" << endl;cout << "tand(x)  - 正切函數(x為角度)" << endl;cout << "\n=== 其他數學函數 ===" << endl;cout << "sqrt(x)  - 平方根" << endl;cout << "log(x)   - 自然對數" << endl;cout << "log10(x) - 常用對數" << endl;cout << "exp(x)   - 指數函數" << endl;cout << "abs(x)   - 絕對值" << endl;cout << "ceil(x)  - 向上取整" << endl;cout << "floor(x) - 向下取整" << endl;cout << "\n=== 角度轉換函數 ===" << endl;cout << "deg2rad(x) - 角度轉弧度" << endl;cout << "rad2deg(x) - 弧度轉角度" << endl;cout << "\n支持的操作符: +, -, *, /, ^, ** (冪運算)" << endl;cout << "支持括號: ( )" << endl;cout << "\n使用示例:" << endl;cout << "sind(30)     → 0.5 (30度的正弦值)" << endl;cout << "cosd(60)     → 0.5 (60度的余弦值)" << endl;cout << "sin(deg2rad(30)) → 0.5 (先轉弧度再計算)" << endl;}
};int main() {Calculator calc;string input;cout << "=== 簡易計算器 (C++98兼容版) ===" << endl;cout << "輸入 'help' 查看支持的函數" << endl;cout << "輸入 'demo' 查看中綴轉后綴演示" << endl;cout << "輸入 'quit' 退出程序" << endl;cout << "\n重要提示:" << endl;cout << "? 角度計算請使用: sind(30), cosd(60), tand(45)" << endl;cout << "? 弧度計算請使用: sin(1.57), cos(3.14), tan(0.78)" << endl;cout << "? 不支持°符號,請直接輸入數字" << endl;cout << "? 編譯時請使用: g++ calculator.cpp -o calculator -lm" << endl;cout << "=================================" << endl;while (true) {cout << "\n請輸入表達式: ";getline(cin, input);if (input == "quit" || input == "exit") {cout << "謝謝使用!" << endl;break;}if (input == "help") {calc.showSupportedFunctions();continue;}if (input == "demo") {cout << "\n=== 中綴轉后綴演示 ===" << endl;calc.showInfixToPostfix("3 + 4 * 2 / ( 1 - 5 ) ^ 2");calc.showInfixToPostfix("sind(30) + cosd(60)");calc.showInfixToPostfix("sqrt(16) + log10(100)");cout << "\n=== 角度vs弧度計算演示 ===" << endl;cout << "sind(30) = " << calc.calculate("sind(30)") << " (30度的正弦值)" << endl;cout << "sin(30)  = " << calc.calculate("sin(30)") << " (30弧度的正弦值)" << endl;cout << "cosd(60) = " << calc.calculate("cosd(60)") << " (60度的余弦值)" << endl;cout << "cos(60)  = " << calc.calculate("cos(60)") << " (60弧度的余弦值)" << endl;cout << "sin(deg2rad(30)) = " << calc.calculate("sin(deg2rad(30))") << " (先轉弧度)" << endl;continue;}if (input.empty()) {continue;}try {double result = calc.calculate(input);cout << "結果: " << fixed << setprecision(6) << result << endl;} catch (const exception& e) {cout << "錯誤: " << e.what() << endl;}}return 0;
}

七、總結與擴展思考

通過這個項目,我們深入學習了表達式求值的完整實現過程,掌握了從詞法分析語法解析再到求值計算的核心技術。這個計算器不僅是一個實用的工具,更是理解編譯原理算法設計的絕佳實踐。

主要技術收獲:

  • 深入理解了調度場算法的工作原理
  • 掌握了詞法分析器的設計與實現
  • 學會了使用函數指針映射實現動態調用
  • 體驗了面向對象設計的封裝和擴展性

可能的擴展方向:

  • 支持變量定義表達式存儲
  • 添加矩陣運算復數計算
  • 實現圖形化界面Web版本
  • 支持自定義函數定義和腳本執行

這個項目為我們打開了計算機語言處理的大門,無論是后續學習編譯器設計,還是開發更復雜的數學計算工具,都有著重要的參考價值。

創作者:Code_流蘇(CSDN)(一個喜歡古詩詞和編程的Coder😊)

·

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/908548.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/908548.shtml
英文地址,請注明出處:http://en.pswp.cn/news/908548.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

WPF八大法則:告別模態窗口卡頓

?? 核心問題&#xff1a;阻塞式模態窗口的缺陷 原始代碼中ShowDialog()會阻塞UI線程&#xff0c;導致后續邏輯無法執行&#xff1a; var result modalWindow.ShowDialog(); // 線程阻塞 ProcessResult(result); // 必須等待窗口關閉根本問題&#xff1a…

UOS無法安裝deb軟件包

UOS無法安裝deb軟件包 問題描述解決辦法: 關閉安全中心的應用隔離結果驗證 問題描述 UOS安裝Linux微信的deb包時&#xff0c;無法正常安裝 解決辦法: 關閉安全中心的應用隔離 要關閉-安全中心的應用隔離后才可以正常軟件和運行。 應用安全----》 允許任意應用。 結果驗證 # …

鴻蒙jsonToArkTS_工具exe版本來了

前言導讀 相信大家在學習鴻蒙開發過程中最痛苦的就是編寫model 類 特別是那種復雜的json的時候對不對&#xff0c; 這時候有一個自動化的工具給你生成model是不是很開心。我們今天要分享的就是這個工具 JsonToArkTs 的用法 工具地址 https://gitee.com/qiuyu123/jsontomodel…

【Java算法】八大排序

八大排序算法 目錄 注意&#xff1a;以下排序均屬于內部排序 &#xff08;1&#xff09;插入排序 直接插入排序 改進版本 折半插入排序 希爾排序 &#xff08;2&#xff09;交換排序 冒泡排序 快速排序 &#xff08;3&#xff09;選擇排序 簡單選擇排序 堆排序&…

玩轉Docker | 使用Docker部署Qwerty Learner英語單詞學習網站

玩轉Docker | 使用Docker部署Qwerty Learner英語單詞學習網站 前言一、Qwerty Learner簡介Qwerty Learner 簡介主要特點二、系統要求環境要求環境檢查Docker版本檢查檢查操作系統版本三、部署Qwerty Learner服務下載Qwerty Learner鏡像編輯部署文件創建容器檢查容器狀態檢查服務…

Vue3中computed和watch的區別

文章目錄 前言&#x1f50d; 一、computed vs watch? 示例對比1. computed 示例&#xff08;適合模板綁定、衍生數據&#xff09;2. watch 示例&#xff08;副作用&#xff0c;如調用接口&#xff09; &#x1f9e0; 二、源碼實現原理&#xff08;簡化理解&#xff09;1. comp…

C++修煉:C++11(二)

Hello大家好&#xff01;很高興我們又見面啦&#xff01;給生活添點passion&#xff0c;開始今天的編程之路&#xff01; 我的博客&#xff1a;<但凡. 我的專欄&#xff1a;《編程之路》、《數據結構與算法之美》、《題海拾貝》、《C修煉之路》 歡迎點贊&#xff0c;關注&am…

單元測試與QTestLib框架使用

一.單元測試的意義 在軟件開發中&#xff0c;單元測試是指對軟件中最小可測試單元&#xff08;通常是函數、類的方法&#xff09;進行隔離的、可重復的驗證。進行單元測試具有以下重要意義&#xff1a; 1.提升代碼質量與可靠性&#xff1a; 早期錯誤檢測&#xff1a; 在開發…

(附實現代碼)Step-Back 回答回退策略擴大檢索范圍

1. LangChain 少量示例提示模板 在與 LLM 的對話中&#xff0c;提供少量的示例被稱為 少量示例&#xff0c;這是一種簡單但強大的指導生成的方式&#xff0c;在某些情況下可以顯著提高模型性能&#xff08;與之對應的是零樣本&#xff09;&#xff0c;少量示例可以降低 Prompt…

16-Oracle 23 ai-JSON-Relational Duality-知識準備

一直做DBA的小伙伴&#xff0c;是不是對開發相對陌生一些。JSON 關系二元性是 Oracle Database 23ai 中重要的特性&#xff0c;同時帶來的是范式革命。JSON關系二元性解決了數據庫領域的根本矛盾?&#xff0c;結構化數據的嚴謹性與半結構化數據的靈活性之間的矛盾。 JSON Rela…

什么是預訓練?深入解讀大模型AI的“高考集訓”

1. 預訓練的通俗理解&#xff1a;AI的“高考集訓” 我們可以將預訓練&#xff08;Pre-training&#xff09; 形象地理解為大模型AI的“高考集訓”。就像學霸在高考前需要刷五年高考三年模擬一樣&#xff0c;大模型在正式誕生前&#xff0c;也要經歷一場聲勢浩大的“題海戰術”…

思爾芯攜手Andes晶心科技,加速先進RISC-V 芯片開發

在RISC-V生態快速發展和應用場景不斷拓展的背景下&#xff0c;芯片設計正面臨前所未有的復雜度挑戰。近日&#xff0c;RISC-V處理器核領先廠商Andes晶心科技與思爾芯&#xff08;S2C&#xff09;達成重要合作&#xff0c;其雙核單集群AX45MPV處理器已在思爾芯最新一代原型驗證系…

vscode配置lua

官網下載lua得到如下 打開vscode的擴展下載如下三個 打開vscode的此處設置 搜索 executorMap&#xff0c;并添加如下內容

理解 RAG_HYBRID_BM25_WEIGHT:打造更智能的混合檢索增強生成系統

目錄 理解 RAG_HYBRID_BM25_WEIGHT&#xff1a;打造更智能的混合檢索增強生成系統 一、什么是 Hybrid RAG&#xff1f; 二、什么是 RAG_HYBRID_BM25_WEIGHT&#xff1f; 三、參數設置示例 四、什么時候該調整它&#xff1f; 五、實戰建議 六、總結 理解 RAG_HYBRID_BM25…

Spring Boot 2 中 default-autowire 的使用

Spring Boot 2 中 default-autowire 的使用 在 Spring Boot 2 中&#xff0c;default-autowire 這個來自傳統 XML 配置的概念仍然存在&#xff0c;但它的使用已經大大減少&#xff0c;因為現代 Spring Boot 應用主要使用注解驅動的配置方式。 default-autowire 在 Spring Boo…

Spring Boot + Thymeleaf 防重復提交

在 Spring Boot 與 Thymeleaf 結合的 Web 應用中&#xff0c;防止重復提交可以采用token 機制 客戶端禁用按鈕的方式實現&#xff0c;在高并發場景下&#xff0c;考慮使用 Redis 存儲 token 而非 Session。 第一步&#xff1a;后端實現 Controller public class FormControl…

【20250607接單】Spark + Scala + IntelliJ 項目的開發環境配置從零教學

本教程適用于零基礎、一臺剛裝好 Windows 的全新電腦開始&#xff0c;搭建能運行 Spark Scala IntelliJ 項目的開發環境。以下是超詳細、小白級別逐步教程&#xff0c;從“下載什么”到“點擊哪里”都幫你列清楚。 &#x1f3af; 目標 操作系統&#xff1a;Windows10/11工具…

【ubuntu】虛擬機安裝配置,sh腳本自動化,包含 apt+時間同步+docker+mysql+redis+pgsql

可以說是ubuntu基礎環境搭建合集&#xff0c;個人學習用&#xff0c;使用sh一鍵安裝&#xff0c;避免復制各種命令 流程主要包括 0. 可選擇不同ubuntu版本對應安裝&#xff08;支持 Ubuntu 20.04/22.04/23.04/24.04&#xff09; 1. apt換源aliyun 2. 時間選擇上海時區&#x…

Rust 學習筆記:關于智能指針的練習題

Rust 學習筆記&#xff1a;關于智能指針的練習題 Rust 學習筆記&#xff1a;關于智能指針的練習題問題一問題二問題三問題四問題五問題六問題七問題八問題九問題十問題十一 Rust 學習筆記&#xff1a;關于智能指針的練習題 參考視頻&#xff1a; https://www.bilibili.com/vi…

JavaScript ES6 解構:優雅提取數據的藝術

JavaScript ES6 解構&#xff1a;優雅提取數據的藝術 在 JavaScript 的世界中&#xff0c;ES6&#xff08;ECMAScript 2015&#xff09;的推出為開發者帶來了許多革命性的特性&#xff0c;其中“解構賦值”&#xff08;Destructuring Assignment&#xff09;無疑是最受歡迎的功…