利用Java動態編譯計算數學表示式
前幾天要做一個計算數學表示式的題目,本來計劃使用解析表示式的方法來解析各種數學表示式,然後再動態計算表示式的值.後來考慮到這樣程式設計的任務很重,時間有限 後來在網上搜搜,看到使用動態編譯並使用反射機制 ,這樣計算表示式的程式設計就容易多了.下面是我這次程式設計的例子, 請大家看看.
java 程式碼- /*
- 02 * Created on 2006-3-8
- 03 * @author icerain 我的Blog: http://blog.matrix.org.cn/page/icess
- 04 */
- 05
- 06publicinterface
- 07 String SIN = "sin";
- 08 String COS = "cos";
- 09 String TAN = "tan";
- 10 String ASIN = "asin";
- 11 String ACOS = "acos";
- 12 String ATAN = "atan";
- 13 String EXP = "exp";
- 14 String LOG = "log";
- 15 String POW = "pow"
- 16 String SQRT = "sqrt";
- 17 String FABS = "fabs";
- 18 String MINUS = "minus";
- 19
- 20 String J_SIN = "Math.sin";
- 21 String J_COS = "Math.cos";
- 22 String J_TAN = "Math.tan";
- 23 String J_ASIN = "Math.asin";
- 24 String J_ACOS = "Math.acos"
- 25 String J_ATAN = "Math.atan";
- 26 String J_EXP = "Math.exp";
- 27 String J_LOG = "Math.log10";
- 28 String J_POW = "Math.pow";
- 29 String J_SQRT = "Math.sqrt";
- 30 String J_FABS = "Math.abs";
- 31
- 32 }
- 定義一個介面, 用來轉換各種數學符號為Java類庫中的表示式.
- 下面是用來計算的程式碼.
- 001/*
- 002 * Created on 2006-3-7
- 003 * @author icerain 我的Blog: http://blog.matrix.org.cn/page/icess
- 004 */
- 005//package hust.icess.simpson;
- 006
- 007
- 008import java.util.logging.Level;
- 009
- 010import java.io.*;
- 011import java.lang.reflect.Method;
- 012import java.util.Scanner;
- 013import java.util.logging.Logger;
- 014
- 015
- 016import com.sun.tools.javac.*;
- 017/**
- 018 * 利用Simpson公式計算積分,在輸入被積公式時候請注意使用如下格式.
- 019 * 1.只使用圓括號() , 沒有別的括號可以使用.如: 1/(1+sin(x))
- 020 * 2.在輸入超越函式的時候,變數和數值用括號擴起來 如:sin(x) 而不要寫為 sinx
- 021 * 3.在兩個數或者變數相乘時候,不要省略乘號* 如:2*a 不要寫為 2a
- 022 * 4.在寫冪運算的時候,請使用如下格式:
- 023 * 利用動態編譯來計算Simpson積分,使用該方法 程式設計相對簡單,執行效率有點慢.
- 024 * @author icerain
- 025 *
- 026 */
- 027publicclass Simpson implements IOperator {
- 028/**
- 029 * Logger for this class
- 030 */
- 031privatestaticfinal Logger logger = Logger.getLogger(Simpson.class
- 032 .getName());
- 033
- 034private String expression = null;
- 035
- 036private String variable = null;
- 037
- 038private String[] variableValue = new String[3];
- 039
- 040// private static Main javac = new Main();
- 041
- 042/**主函式 */
- 043publicstaticvoid main(String[] args) throws Exception {
- 044 Simpson sim = new Simpson();
- 045 System.out.println("結果如下:");
- 046 System.out.print(sim.getSimpsonValue());
- 047 System.exit(0);
- 048
- 049 }
- 050
- 051public Simpson() {
- 052 logger.setLevel(Level.WARNING);
- 053 init();
- 054 }
- 055
- 056/** 初始化使用者輸入,為技術Simpson積分做準備. */
- 057privatevoid init() {
- 058 Scanner scanner = new Scanner(System.in);
- 059 System.out.println("請輸入函式表示式 如 1+sin(a) + cos(a)/a :");
- 060// String input = scanner.nextLine();
- 061//讀入被積函式的表示式
- 062 expression = scanner.nextLine().trim().toLowerCase();
- 063 System.out.println("請輸入變數字元 如 a :");
- 064//讀入變數字元
- 065 variable = scanner.nextLine().trim().toLowerCase();
- 066
- 067//處理多元函式 目前不實現該功能
- 068// String[] tempVars = tempVar.split(" ");
- 069// for(int i = 0; i < tempVars.length; i ++) {
- 070// variable[i] = tempVars[i];
- 071// }
- 072
- 073 System.out.println("請輸入積分割槽間和結點數 如 2 5.4 10 :");
- 074//讀取複合Simpson公式的積分引數
- 075 String tempValue = scanner.nextLine().trim();
- 076 String[] tempValues = tempValue.split(" ");
- 077for (int i = 0; i < tempValues.length; i++) {
- 078 variableValue[i] = tempValues[i];
- 079 }
- 080
- 081 }
- 082
- 083/** 計算 Simpson積分的值*/
- 084publicdouble getSimpsonValue() {
- 085//儲存中間結果
- 086double value1 = 0;
- 087double value2 = 0;
- 088double tempValue = 0;
- 089int i = 0;
- 090// 解析輸入的積分引數值
- 091int n = Integer.parseInt(variableValue[2]);
- 092double a = Double.parseDouble(variableValue[0]);
- 093double b = Double.parseDouble(variableValue[1]);
- 094double h = (b - a) / n;
- 095//計算value1
- 096for (i = 0; i < n; i++) {
- 097 tempValue = a + (i + 0.5) * h;
- 098 String code = getSourceCode(expression, getVariable(), Double
- 099 .toString(tempValue));
- 100try {
- 101 value1 += run(compile(code));
- 102 } catch (Exception e) {
- 103// TODO Auto-generated catch block
- 104 e.printStackTrace();
- 105
- 106if (logger.isLoggable(Level.INFO)) {
- 107 logger.info("something is wrong");
- 108 }
- 109 }
- 110 }
- 111//計算value2
- 112for (i = 1; i < n; i++) {
- 113 tempValue = a + i * h;
- 114 String code = getSourceCode(expression, getVariable(), Double
- 115 .toString(tempValue));
- 116try {
- 117 value2 += run(compile(code));
- 118 } catch (Exception e) {
- 119// TODO Auto-generated catch block
- 120 e.printStackTrace();
- 121if (logger.isLoggable(Level.INFO)) {
- 122 logger.info("something is wrong");
- 123 }
- 124 }
- 125 }
- 126
- 127//計算f(a) f(b) 的函式值
- 128double valueA = getFunctionValue(a);
- 129double valueB = getFunctionValue(b);
- 130//計算Simpson公式的值
- 131double resultValue = (valueA + valueB + 4 * value1 + 2 * value2) * h / 6;
- 132
- 133return resultValue;
- 134 }
- 135
- 136//計算F(a) 的值
- 137privatedouble getFunctionValue(double varValue) {
- 138 String code = getSourceCode(expression, getVariable(), Double
- 139 .toString(varValue));
- 140double result = 0;
- 141try {
- 142 result = run(compile(code));
- 143 } catch (Exception e) {
- 144// TODO Auto-generated catch block
- 145 e.printStackTrace();
- 146if (logger.isLoggable(Level.INFO)) {
- 147 logger.info("something is wrong");
- 148 }
- 149 }
- 150return result;
- 151 }
- 152
- 153/**
- 154 * 得到使用者輸入表示式轉換為Java中的可計算表示式的函式
- 155 * @param ex 輸入的表示式 如: 1/(1 + sin(x))
- 156 * @param var 表示式中的變數 如: x
- 157 * @param value 變數的取值 如: 4.3
- 158 * @return Java中可以直接計算的表示式 如: 1/(1 + Math.sin(x))
- 159 */
- 160private String getSourceCode(String ex, String var, String value) {
- 161 String expression = ex;
- 162//計算多個變數的函式的時候使用
- 163
- 164 expression = expression.replaceAll(var, value);
- 165
- 166//處理數學符號
- 167if (expression.contains(SIN)) {
- 168 expression = expression.replaceAll(SIN, J_SIN);
- 169 } elseif (expression.contains(COS)) {
- 170 expression = expression.replaceAll(COS, J_COS);
- 171 } elseif (expression.contains(TAN)) {
- 172 expression = expression.replaceAll(TAN, J_TAN);
- 173 } elseif (expression.contains(ASIN)) {
- 174 expression = expression.replaceAll(ASIN, J_ASIN);
- 175 } elseif (expression.contains(ACOS)) {
- 176 expression = expression.replaceAll(ACOS, J_ACOS);
- 177 } elseif (expression.contains(ATAN)) {
- 178 expression = expression.replaceAll(ATAN, J_ATAN);
- 179 } elseif (expression.contains(EXP)) {
- 180 expression = expression.replaceAll(EXP, J_EXP);
- 181 } elseif (expression.contains(LOG)) {
- 182 expression = expression.replaceAll(LOG, J_LOG);
- 183 } elseif (expression.contains(POW)) {
- 184 expression = expression.replaceAll(POW, J_POW);
- 185 } elseif (expression.contains(SQRT)) {
- 186 expression = expression.replaceAll(SQRT, J_SQRT);
- 187 } elseif (expression.contains(FABS)) {
- 188 expression = expression.replaceAll(FABS, J_FABS);
- 189 }
- 190
- 191return expression;
- 192 }
- 193
- 194/** 編譯JavaCode,返回java檔案*/
- 195privatesynchronized File compile(String code) throws Exception {
- 196 File file;
- 197// 建立一個臨時java原始檔
- 198 file = File.createTempFile("JavaRuntime", ".java", new File(System
- 199 .getProperty("user.dir")));
- 200if (logger.isLoggable(Level.INFO)) {
- 201 logger.info(System.getProperty("user.dir"));
- 202 }
- 203// 當Jvm 退出時 刪除該檔案
- 204 file.deleteOnExit();
- 205// 得到檔名和類名
- 206 String filename = file.getName();
- 207if (logger.isLoggable(Level.INFO)) {
- 208 logger.info("FileName: " + filename);
- 209 }
- 210 String classname = getClassName(filename);
- 211// 將程式碼輸出到原始碼檔案中
- 212 PrintWriter out = new PrintWriter(new FileOutputStream(file));
- 213// 動態構造一個類,用於計算
- 214 out.write("public class " + classname + "{"
- 215 + "public static double main1(String[] args)" + "{");
- 216 out.write("double result = " + code + ";");
- 217//用於除錯
- 218//out.write("System.out.println(result);");
- 219 out.write("return new Double(result);");
- 220 out.write("}}");
- 221//關閉檔案流
- 222 out.flush();
- 223 out.close();
- 224//設定編譯引數
- 225 String[] args = new String[] { "-d", System.getProperty("user.dir"),
- 226 filename };
- 227//除錯
- 228if (logger.isLoggable(Level.INFO)) {
- 229 logger.info("編譯引數: " + args[0]);
- 230 }
- 231//Process process = Runtime.getRuntime().exec("javac " + filename);
- 232int status = Main.compile(args);
- 233//輸出執行的狀態碼.
- 234// 狀態引數與對應值
- 235// EXIT_OK 0
- 236// EXIT_ERROR 1
- 237// EXIT_CMDERR 2
- 238// EXIT_SYSERR 3
- 239// EXIT_ABNORMAL 4
- 240if (logger.isLoggable(Level.INFO)) {
- 241 logger.info("Compile Status: " + status);
- 242 }
- 243//System.out.println(process.getOutputStream().toString());
- 244return file;
- 245 }
- 246
- 247/**
- 248 * 執行程式 如果出現Exception 則不做處理 丟擲!
- 249 * @param file 執行的檔名
- 250 * @return 得到的Simpson積分公式的結果
- 251 * @throws Exception 丟擲Exception 不作處理
- 252 */
- 253privatesynchronizeddouble run(File file) throws Exception {
- 254 String filename = file.getName();
- 255 String classname = getClassName(filename);
- 256 Double tempResult = null;
- 257// System.out.println("class Name: " +classname);
- 258//當Jvm 退出時候 刪除生成的臨時檔案
- 259new File(file.getParent(), classname + ".class").deleteOnExit();
- 260try {
- 261 Class cls = Class.forName(classname);
- 262//System.out.println("run........");
- 263// 對映main1方法
- 264 Method calculate = cls
- 265 .getMethod("main1", new Class[] { String[].class });
- 266//執行計算方法 得到計算的結果
- 267 tempResult = (Double) calculate.invoke(null,
- 268new Object[] { new String[0] });
- 269 } catch (SecurityException se) {
- 270 System.out.println("something is wrong !!!!");
- 271 System.out.println("請重新執行一遍");
- 272 }
- 273//返回值
- 274return tempResult.doubleValue();
- 275 }
- 276
- 277/** 除錯函式*/
- 278// private void debug(String msg) {
- 279// System.err.println(msg);
- 280// }
- 281
- 282/** 得到類的名字 */
- 283private String getClassName(String filename) {
- 284return filename.substring(0, filename.length() - 5);
- 285 }
- 286
- 287
- 288//getter and setter
- 289public String getExpression() {
- 290return expression;
- 291 }
- 292
- 293publicvoid setExpression(String expression) {
- 294this.expression = expression;
- 295 }
- 296
- 297public String getVariable() {
- 298return variable;
- 299 }
- 300
- 301publicvoid setVariable(String variable) {
- 302this.variable = variable;
- 303 }
- 304
- <spa>
相關推薦
利用Java動態編譯計算數學表示式
前幾天要做一個計算數學表示式的題目,本來計劃使用解析表示式的方法來解析各種數學表示式,然後再動態計算表示式的值.後來考慮到這樣程式設計的任務很重,時間有限 後來在網上搜搜,看到使用動態編譯並使用反射機制 ,這樣計算表示式的程式設計就容易多了.下面是我這次程式設計的例子, 請大
java 動態編譯
runtime {} runt mpi src lan provider null roc 1.第一種方式:JavaCompiler+Runntime public static void run() { JavaCompiler compiler
Java動態編譯和動態載入詳解
一.動態編譯 在某些情況下,我們需要動態生成java程式碼,通過動態編譯,然後執行程式碼。JAVA API提供了相應的工具(JavaCompiler)來實現動態編譯。 //獲取JavaCompiler JavaCompiler compiler = ToolProvider.getSyste
[bash]判斷三角形型別、計算數學表示式、計算N個整數的指定精度的平均值
判斷三角形為等邊三角形、等腰三角形或不等邊三角形 #!/bin/bash #https://www.hackerrank.com/challenges/bash-tutorials---more-on-conditionals/problem read a read b read c
java動態編譯class,動態載入類,執行載入類的方法,直接可執行測試
直接上圖上程式碼 public static void main(String[] args) { TestClass testClass=new TestClass(); try { //動態編譯程式碼 Java
java動態編譯 (java線上執行程式碼後端實現原理)
需求:要實現一個web網頁中輸入java程式碼,然後能知道編譯結果以及執行結果 類似於菜鳥java線上工具的效果:https://c.runoob.com/compile/10 剛開始從什麼概念都沒有到最後封裝成一個完整的工具類,中間查閱了很多資料才瞭解其中的概念以及流程,參考文獻在文章最後面。 重點需要
Java動態編譯優化——提升編譯速度(N倍)
一、前言 最近一直在研究Java8 的動態編譯, 並且也被ZipFileIndex$Entry 記憶體洩漏所困擾,在無意中,看到一個第三方外掛的動態編譯。並且編譯速度是原來的2-3倍。原本打算直接用這個外掛,但是發現外掛的編譯原始碼存在我之前已經解決過的記憶體洩漏問題。所以拿其原始碼,進行改
Java動態編譯優化——ZipFileIndex記憶體洩漏問題分析解決
一、前言: 前幾天解決了URLClassLoader記憶體洩漏的問題,但是解決問題就像剝洋蔥,剝去了外層,內層 問題又暴露出來了。當URLClassLoader記憶體洩漏解決, 需要解決的就是ZipFileIndex記憶體洩漏的問題了,而且這個問題折騰了我2天半的時間。 URLClass
Java動態編譯優化——URLClassLoader 記憶體洩漏問題解決
一、動態編譯案例 要說動態編譯記憶體洩漏,首先我們先看一個案例(網上搜動態編譯的資料是千篇一律,只管實現功能,不管記憶體洩漏,並且都恬不知恥的標識為原創!!) Java URLClassLoader 動態編譯案例:https://blog.csdn.net/huangshan
JVM調優——Java動態編譯過程中的記憶體溢位問題
由於測試環境專案每2小時記憶體就溢位一次, 分析問題,發現Java動態載入Class並執行那塊存在記憶體溢位問題, 遂本地調測。 一、找到動態編譯那塊的程式碼,具體如下 /** * @MethodName : 編譯java程式碼到Object * @Descrip
利用Java裡的正則表示式求一群人身份證上的出生年月日
package Regex; import java.util.regex.*; import java.util.regex.Matcher; public class testIdCard { public static void main(String[] ar
利用Java 動態代理,自定義註解 讀取配置檔案中的屬性值
Java動態代理在一些中介軟體中經常用到,或者一些大型專案中都會用到。 這裡順帶使用一下自定義註解方式,基於java 反射機制讀取.properties格式檔案。 demo的大致內容包含以下: 1.配置檔案:config.properties url=http://www.
Groovy&Java動態編譯執行
工作中,遇到部分業務經常動態變化,或者在不釋出系統的前提下,對業務規則進行調整。那麼可以將這部分業務邏輯改寫成Groovy指令碼來執行,那麼就可以在業務執行過程中動態更改業務規則,達到快速響應。 Case1: Groovy動態編譯執行 閒話少說,直接上程式碼: stati
【Big Data 每日一題20180822】Java動態編譯優化——URLClassLoader 記憶體洩漏問題解決
一、動態編譯案例 要說動態編譯記憶體洩漏,首先我們先看一個案例(網上搜動態編譯的資料是千篇一律,只管實現功能,不管記憶體洩漏,並且都恬不知恥的標識為原創!!) 這篇文章和我google搜的其他文章、資料一樣,屬於JDK1.6以後的版本。確實能實現動態編譯並載入,但
Java 動態編譯時出現空指標異常
如題:問題原因檢視該播客:http://www.cnblogs.com/fangwenyu/archive/2011/10/12/2209051.html解決方法就是將java/jdk/tools.jar檔案拷貝到java/jre/lib下面。我安裝java的時候將檔案分開了
java 動態編譯&load
有時候我們需要把一些外部資源(比如第三方jar,自己動態生成的java檔案)編譯並載入到classloader,這時我們就需要JavaCompiler 個類,jdk是從1.6開始支援此功能 網上有很多類似列子,搜尋“動態編譯”可以找到,我這裡只列出一種實現方法
Java動態編譯
code rgs pac 工程 tool getname rri n) tac Java動態編譯 最近熟悉了一下反射,對Java的動態性有了進一步的了解,因此想實現一下用Java直接動態生成.class文件,也就是在編譯完成後,運行時編譯java文件 工程結構 ? hel
利用Java的動態編譯、動態載入結合EasyRules實現業務規則的動態性
作為一名專門寫bug的Java程式猿,相信大家都會遇到過這樣的問題:專案的業務邏輯很複雜,而且還經常變化,今天的一個辦理條件是小於5,明天就變成了大於10或者條件作廢。這就很頭疼了,裡面的數字可以抽取到配置檔案,但是大於和小於呢?條件作廢呢? 對於業務規則的複雜性,我們可以使用一些規則引擎來
利用javax.tools動態編譯執行java程式碼
javax.tools 包是一種新增到 Java SE 6 的標準 API,可以實現 Java 原始碼編譯,使您能夠新增動態功能來擴充套件靜態應用程式。本文將探查javax.tools包中提供的主要類,以Java表示式表示計算一個數值函式y=x*x+x。更多詳情請參
在java中利用動態編譯實現eval
我們知道,在很多指令碼語言中都有eval涵數,它可以把字串轉換為表態式並執行.如在javaScript中var str = aid.value + ".style.top = 10;"把一個id為"aid"的控制的值取出來加合併成一個字串,如果aid的值是"axman",則s