计算器是经常遇到的编程作业。
一般都是实现加、减、乘、除四则运算的普通计算器。
这里介绍用几十行C#代码实现的复杂的《科学计算器》,可以计算各种函数。
不知道其他语言实现同样的功能需要编写多少行代码?20000行?
using System;
 using System.Text;
 using System.Drawing;
 using System.Collections.Generic;
 using System.Windows.Forms;
 using System.CodeDom.Compiler;
 using Microsoft.CSharp;
 using System.Reflection;
  
 namespace HyperCalculator
 {
     public partial class Form1 : Form
     {
         // 预定义各 按键 的文字
         string[] operationArray = new string[] {
             "Abs",  "Acos", "(",    ",",    ")",    "Backspace",   "C",
             "Asin", "Atan", "7",    "8",    "9",    "/",    "=",
             "Atan2",    "Ceiling",  "4",    "5",    "6",    "*",    "",
             "Cos",  "Cosh", "1",    "2",    "3", "-",    "",
             "E",    "Exp",  "0",    "", ".",    "+",    "",
             "Floor",    "Log",  "Log10",    "Max",  "Min",   "PI",   "Pow",
             "Sign", "Sin",  "Sinh", "Sqrt", "Tan",  "Tanh", "",
         };
         List<Button> buttonList = new List<Button>();
         public Form1()
         {
             InitializeComponent();
         }
         private void Form1_Load(object sender, EventArgs e)
         {
             // 动态加载液晶LED字体(请下载压缩包,内含)
             System.Drawing.Text.PrivateFontCollection privateFonts = new System.Drawing.Text.PrivateFontCollection();
             privateFonts.AddFontFile("LEDCalculatorBold.ttf");
             System.Drawing.Font font = new Font(privateFonts.Families[0], 21);
             textBox1.Font = font;
             textBox1.Text = "0";
             textBox1.TextAlign = HorizontalAlignment.Right;
             // 打包按键集合
             Control.ControlCollection sonControls = this.Controls;
             foreach (Control control in sonControls)
             {
                 if (control.GetType() == typeof(Button))
                 {
                     buttonList.Add((Button)control);
                 }
             }
             // 按位置排序,以及匹配实现预定义的文字
             buttonList.Sort(delegate (Button a, Button b)
             {
                 return Comparer<int>.Default.Compare(a.Left + a.Top * button1.Height, b.Left + b.Top * button1.Height);
             });
             Font nf = new Font(Font.FontFamily, 21);
             for (int i = 0; i < buttonList.Count && i < operationArray.Length; i++)
             {
                 buttonList[i].Cursor = Cursors.Hand;
                 buttonList[i].Text = operationArray[i];
                 if (buttonList[i].Text.Length == 1 && operationArray[i] != "E")
                 {
                     buttonList[i].Font = nf;
                     buttonList[i].BackColor = Color.FromArgb(225, 255, 200);
                 }
                 if (operationArray[i].Trim().Length > 0) buttonList[i].Click += button_Click;
             }
         }
  
         private void button_Click(object sender, EventArgs e)
         {
             Button btn = (Button)sender;
             if (btn.Text == "=")
             {
                 // 等号就是计算啦!任何计算,都是执行一个表达式而已!
                 CSharpCodeProvider objCSharpCodePrivoder = new CSharpCodeProvider();
                 ICodeCompiler objICodeCompiler = objCSharpCodePrivoder.CreateCompiler();
                 CompilerParameters objCompilerParameters = new CompilerParameters();
                 objCompilerParameters.ReferencedAssemblies.Add("System.dll");
                 objCompilerParameters.GenerateExecutable = false;
                 objCompilerParameters.GenerateInMemory = true;
                 // 编译 Code() 返回的含有计算表达式的完整的 C# 程序;
                 CompilerResults cr = objICodeCompiler.CompileAssemblyFromSource(objCompilerParameters, Code());
                 if (cr.Errors.HasErrors)
                 {
                     StringBuilder sb = new StringBuilder();
                     foreach (CompilerError err in cr.Errors)
                     {
                         sb.AppendLine(err.ErrorText);
                     }
                     MessageBox.Show(sb.ToString(), "表达式错误");
                 }
                 else
                 {
                     // 执行 C# 程序的指定 函数,并得到返回值,就是计算结果;
                     Assembly objAssembly = cr.CompiledAssembly;
                     object objHelloWorld = objAssembly.CreateInstance("Beijing.Legalsoft.Ltd.HyperCalculator");
                     MethodInfo objMI = objHelloWorld.GetType().GetMethod("Run");
                     double resultValue = (double)objMI.Invoke(objHelloWorld, null);
                     textBox1.Text = resultValue + "";
                 }
                 return;
             }
             if (btn.Text == "C")
             {
                 textBox1.Text = "0";
                 return;
             }
             if (btn.Text == "Backspace")
             {
                 if (textBox1.Text.Length > 1)
                 {
                     textBox1.Text = textBox1.Text.Substring(0, textBox1.Text.Length - 1);
                 }
                 else
                 {
                     textBox1.Text = "0";
                 }
                 return;
             }
             if (textBox1.Text == "0") textBox1.Text = "";
             if (textBox1.Text.Length + btn.Text.Length < 45)
             {
                 textBox1.Text += btn.Text;
             }
         }
         private string Code()
         {
             // 按输入的文字构造一个完整的 C# 程序;包括命名空间,类与方法(函数)
             string state = textBox1.Text;
             foreach (string ps in operationArray)
             {
                 if (ps.Trim().Length > 1 || ps == "E")
                 {
                     state = state.Replace(ps, "Math." + ps);
                 }
             }
             state = state.Replace("Math.Math.", "Math.");
             StringBuilder sb = new StringBuilder();
             sb.AppendLine("using System;");
             sb.AppendLine("namespace Beijing.Legalsoft.Ltd");
             sb.AppendLine("{");
             sb.AppendLine("    public class HyperCalculator");
             sb.AppendLine("    {");
             sb.AppendLine("        public double Run()");
             sb.AppendLine("        {");
             sb.AppendLine("            return (" + state + ");");
             sb.AppendLine("        }");
             sb.AppendLine("    }");
             sb.AppendLine("}");
             return sb.ToString();
         }
     }
 }




















