C#实现求解函数在某一点的切线与法线函数

csharp 复制代码
using MathNet.Symbolics; 
using System.Text;

private string ConvertToLatex(string mathExpression)
{
    return mathExpression
        .Replace(" * ", "")
        .Replace("*", "")
        .Replace("π",@"\pi")
        .Replace("sin(x)", @"\sin x") 
        .Replace("cos(x)", @"\cos x")
        .Replace("tan(x)", @"\tan x")
        .Replace("cot(x)", @"\cot x")
        .Replace("sec(x)", @"\sec x")
        .Replace("csc(x)", @"\csc x");
}

private string calculate_trigonometric_functions(string expression, bool isLatexFormat = false)
{
    string ret = expression;
    if (expression.Contains("sin(π/3)"))
    {
        /* 
        公式:sin(π/3) = √3/2
        证明:sin(π/3)等于根号三除以2,即√3/2。这是因为在单位圆上,角度π/3对应的弧度是60度,它是一个等边三角形的内角,三角函数sin对应的是对边与斜边的比值,而等边三角形的对边和斜边长度相等,都是边长的根号三倍。因此,sin(π/3)等于根号三除以2。
        */
        ret = ret.Replace("sin(π/3)", isLatexFormat ? "\\frac{\\sqrt{3}}{2}" : "sqrt(3)/2");
    }
    if (expression.Contains("cos(π/3)"))
    {
        /*
        公式:cos(π/3) = 1/2
        证明:考虑一个边长为1的等边三角形,其中每个内角都是60度(π/3弧度)。从一个顶点作垂线到对边,这将等边三角形分割成两个30-60-90的直角三角形。在这样的直角三角形中,较短的直角边(对应于60度角的邻边)是斜边(等边三角形的边)的一半,即1/2。由于余弦函数定义为邻边与斜边的比值,在60度角(π/3弧度)的情况下,这个比值就是1/2。
        */
        ret = ret.Replace("cos(π/3)", isLatexFormat ? "\\frac{1}{2}" : "1/2");
    }
    if (expression.Contains("tan(π/3)"))
    {
        /*
        公式:tan(π/3) = √3
        证明:在直角三角形中,当其中一个锐角是60度时,这个角的对边与邻边的比值遵循特定的比例。具体来说,如果将这个直角三角形的斜边视为单位长度(即1),那么对边(对应于60度角的边)长度为√3,邻边长度为1。因此,根据正切(tan)的定义,即对边与邻边的比值,我们有tan(60°) = tan(π/3) = 对边/邻边 = √3/1 = √3。
        */
        ret = ret.Replace("tan(π/3)", isLatexFormat ? "\\sqrt{3}" : "sqrt(3)");
    }
    if (expression.Contains("cot(π/3)"))
    {
        /*
        公式:cot(π/3) = √3/3
        证明:我们知道tan(π/3) = √3。余切cotθ是正切tanθ的倒数,即cotθ = 1/tanθ。因此,cot(π/3) = 1/tan(π/3) = 1/√3。
        */
        ret = ret.Replace("cot(π/3)", isLatexFormat ? "\\frac{\\sqrt{3}}{3}" : "sqrt(3)/3");
    }
    return ret;
}

// 将函数定义为字符串
string functionString = "cos(x)"; // 将函数解析为符号表达式
SymbolicExpression function = SymbolicExpression.Parse(functionString);
// 代入x=π/3到函数
string x_value = "π/3";
SymbolicExpression val1 = SymbolicExpression.Parse(x_value); 
SymbolicExpression x = SymbolicExpression.Parse("x"); 
SymbolicExpression y = function.Substitute(x, val1); 
string ret_y = calculate_trigonometric_functions(y.ToString(), true);
// 关于x符号化的微分函数
SymbolicExpression derivative = function.Differentiate("x");
// 代入x=π/3到微分函数
SymbolicExpression result = derivative.Substitute(x, val1); 
string ret = result.ToString(); 
if (ret.Contains("sin(π/3)"))
{
    // sin(π/3) = √3/2
    ret = ret.Replace("sin(π/3)", "\\sin \\frac{\\pi}{3}") + "=" + calculate_trigonometric_functions(ret, true);
}
if (ret.Contains("cos(π/3)"))
{
    // cos(π/3) = 1/2
    ret = ret.Replace("cos(π/3)", "\\cos \\frac{\\pi}{3}") + "=" + calculate_trigonometric_functions(ret, true);
}
if (ret.Contains("tan(π/3)"))
{
    // tan(π/3) = √3
    ret = ret.Replace("tan(π/3)", "\\tan \\frac{\\pi}{3}") + "=" + calculate_trigonometric_functions(ret, true);
}
if (ret.Contains("cot(π/3)"))
{
    // cot(π/3) = √3/3
    ret = ret.Replace("cot(π/3)", "\\cot \\frac{\\pi}{3}") + "=" + calculate_trigonometric_functions(ret, true);
}
string latexExpr0 = ConvertToLatex(functionString);
string latexExpr1 = ConvertToLatex(derivative.ToString());//将求解结果函数和值写入Tex文件
string filePath = "derivative_tangents_normals.tex"; // 文件路径 
StringBuilder sb = new StringBuilder(500);
string latexHead = @"\documentclass{article}
\usepackage{amsmath,amssymb,amsfonts}
\usepackage{CJKutf8}
\begin{document}
	\begin{CJK}{UTF8}{gkai}%正文放在此行下与\end{CJK}之间就行
";
string value = x_value.Replace("π","\\pi");
string[] values = value.Split("/");
value = $"\\frac{{{values[0]}}}{{{values[1]}}}";
sb.Append(latexHead);
sb.Append("\r\n");
sb.Append("求曲线$y=" + latexExpr0 + $"$上点$({value},{ret_y})$处的切线方程和法线方程。\r\n");
sb.Append("\r\n");
sb.Append($"解:$y'|_{{x={value}}}=({latexExpr1})|_{{x={value}}}={ret}$,\r\n");
sb.Append("\r\n");
sb.Append($"曲线在点$({value},{ret_y})$处的切线方程为:\r\n");
sb.Append("\r\n");
string tangentsFunction = "y + result * (x - x_value)"; // 将切线函数解析为符号表达式
SymbolicExpression tangents = SymbolicExpression.Parse(tangentsFunction);
SymbolicExpression y0 = SymbolicExpression.Parse("y");
SymbolicExpression result0 = SymbolicExpression.Parse("result");
SymbolicExpression x_value0 = SymbolicExpression.Parse("x_value");
SymbolicExpression tangentsExpression = tangents.Substitute(y0, y).Substitute(result0, result).Substitute(x_value0, x_value);
ret = calculate_trigonometric_functions(tangentsExpression.ToString(), false);
tangentsExpression = SymbolicExpression.Parse(ret);
sb.Append($"$y={tangentsExpression.ToLaTeX()}$,\r\n"); 
sb.Append("\r\n");
sb.Append($"曲线在点$({value},{ret_y})$处的法线方程为:\r\n");
sb.Append("\r\n");
string normalsFunction = "y - result ^ -1 * (x - x_value)"; // 将切线函数解析为符号表达式
SymbolicExpression normals = SymbolicExpression.Parse(normalsFunction);
SymbolicExpression normalsExpression = normals.Substitute(y0, y).Substitute(result0, result).Substitute(x_value0, x_value);
ret = calculate_trigonometric_functions(normalsExpression.ToString(), false);
normalsExpression = SymbolicExpression.Parse(ret);
sb.Append($"$y={normalsExpression.ToLaTeX()}$。\r\n");
string latexTail = @"
\end{CJK}
\end{document}";
sb.Append(latexTail);
string content = sb.ToString(); // 要写入的文本内容 
Encoding utf8bom = new UTF8Encoding(true);
File.WriteAllText(filePath, content, utf8bom);

derivative_tangents_normals.tex文件内容:

xml 复制代码
\documentclass{article}
\usepackage{amsmath,amssymb,amsfonts}
\usepackage{CJKutf8}
\begin{document}
	\begin{CJK}{UTF8}{gkai}%正文放在此行下与\end{CJK}之间就行

	求曲线$y=\cos x$上点$(\frac{\pi}{3},\frac{1}{2})$处的切线方程和法线方程。
	
	解:$y'|_{x=\frac{\pi}{3}}=(-\sin x)|_{x=\frac{\pi}{3}}=-\frac{\sqrt{3}}{2}$,
	
	故曲线在点$(\frac{\pi}{3},\frac{1}{2})$处的切线方程为:

	$y=\frac{1}{2} - \frac{1}{2}\sqrt{3}\left(-\frac{\pi}{3} + x\right)$,

	曲线在点$(\frac{\pi}{3},\frac{1}{2})$处的法线方程为:

	$y=\frac{1}{2} + \frac{-\frac{\pi}{3} + x}{2\sqrt{3}}$。

\end{CJK}
\end{document}
相关推荐
m0_639906946 分钟前
Java 重写 Override 与重载 Overload 区别、访问修饰符、static 关键字
java·开发语言
Evand J7 分钟前
【MATLAB例程】平面下,5基站对待定位点的定位。基于距离辅助下的AOA。完整代码下载链接
开发语言·matlab·平面·定位·导航·测距·aoa
GIS数据转换器20 分钟前
基于CIM的城市智慧供热监管服务平台
java·大数据·开发语言·人工智能·后端·物联网·struts
weixin_4173968335 分钟前
星级酒店境外电视频道怎么合法接入?合规要点与核对清单
开发语言·前端·php·1024程序员节·综合布线
熊猫钓鱼>_>1 小时前
鸿蒙PC构建实战:hvigor modelVersion 降级 + schema 清理 + ArkTS 编译三连坑完整复盘
开发语言·华为·ai编程·harmonyos·openharmony·数据·ai生成
FRing031 小时前
JavaScript入门到精通三十一(原型继承、原型链)
开发语言·前端·javascript
1024奇点1 小时前
【仓颉语言入门 · 第二篇 第 12 课】
开发语言·数据库·ide·mysql·开源
LDR0061 小时前
LDR6100 智能遥控器精品软文:Type-C 充电口与低功耗量产维护
c语言·开发语言
iCxhust2 小时前
MATLAB SPWM仿真
开发语言·matlab
谙忆2 小时前
PNG改成ICO为什么不能用:用Python检查多尺寸目录与256px帧
开发语言·python