日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Fel表达式使用过程中需要注意的问题

發布時間:2023/12/15 33 生活家
生活随笔 收集整理的這篇文章主要介紹了 Fel表达式使用过程中需要注意的问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

精度問題:

我們知道java中直接使用float和double參與的計算都可能會產生精度問題,比如0.1+0.3、1.0-0.9 等。所以一般財務系統,都會使用BigDecimal進行加減乘除。 在調研Fel過程中,發現Fel里進行計算都是使用浮點數加減乘除的,所以不可避免的會產生精度問題。

Case+源碼分析:

加法 Case:

FelEngine fel = new FelEngineImpl();
Object result = fel.eval("0.1+0.2");
System.out.println(result);



源碼分析:

簡單的來說,Fel首先經過詞法解析器將表達式解析成FelNode實例,FelNode包含表達式子節點(比如+號、0.1等)和表達式解析器,解析器對應的有com.greenpineyu.fel.function.operator.Add、ccom.greenpineyu.fel.function.operator.Sub、com.greenpineyu.fel.function.operator.Mul、com.greenpineyu.fel.function.operator.Div等各種解析器(詳見com.greenpineyu.fel.function.operator下的類),具體的表達式運算結果是由這些解析器計算的。具體到方法又是由com.greenpineyu.fel.function.operator.Add#call計算的。

public Object call(FelNode node, FelContext context) {
	Object returnMe = null;
	for (Iterator<FelNode> iterator = node.getChildren().iterator(); iterator.hasNext();) {
		Object child = iterator.next();
		if (child instanceof FelNode) {
			FelNode childNode = (FelNode) child;
			child = childNode.eval(context);
		}
		if (child instanceof String) {
			if (returnMe == null) {
				returnMe = child;
				continue;
			}
				returnMe = returnMe + (String) child;
		}
		if (child instanceof Number) {
			if (returnMe == null) {
				returnMe = child;
				continue;
			}
			Number value = (Number) child;
			if (returnMe instanceof Number) {
				Number r = (Number) returnMe;
				// 注意這里:是直接使用轉成double進行加減的。
				returnMe = toDouble(r) + toDouble(value);
			}else if(returnMe instanceof String){
				String r = (String) returnMe;
				returnMe=r+value;
			}
		}
	}
	if(returnMe instanceof Number){
		return NumberUtil.parseNumber(returnMe.toString());
	}
	return returnMe;
}

/**
 * 將Number轉換成double
 * @param number
 * @return
 */
public static double toDouble(Number number){
	if(number instanceof Float){
		//float轉double時,會出現精度問題。"(double)1.1f"的值類似于1.1000000476837158),
		//使用 Double.parseDouble(number.toString());則不會出現問題。
		return Double.parseDouble(number.toString());
	}
	return number.doubleValue();
}

通過上面的returnMe = toDouble(r) + toDouble(value); 代碼片段,我們就知道Fel是拿double進行加法操作的,這樣某些情況下就會產生精度問題。

其他運算操作同之。

解決辦法:
避免使用浮點數進行數值計算,可以將操作數乘以10的某個倍數,將浮點數轉成整數。至于從整數再轉成浮點數就可以使用BigDecimal了。其實,一個好的財務系統都是不會存儲和使用浮點數的,都是轉成整數,只有在進行頁面顯示的時候才處理回浮點數。

總結

以上是生活随笔為你收集整理的Fel表达式使用过程中需要注意的问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。