2014-12-04 102 views
0

我在支柱兩個領域形成爲:BigDecimal的分工問題

Long currentUsage; // 209715200l 
BigDecimal totalQuota; // 343597383680 

JSP我使用顯示百分比爲:

<c:set var="totalQuota" 
value="${(strutsForm.totalQuota div 1024 div 1024 div 1024)}"></c:set> 
${ ((strutsForm.currentUsage div 1024 div 1024) div (totalQuota)) * 100 } 

但產量正在顯示的是。
爲什麼會發生這種情況?我怎麼能得到正確的結果?

+0

我認爲,最簡單的解決方案是在服務器端執行此計算並在視圖頁上使用結果。 – 2014-12-04 11:05:49

+0

@SemihEker:你說得對。但是我正在尋找它是否可以在jsp上完成。 – 2014-12-04 12:06:57

回答

1

這是怎麼發生的?

這是直覺的行爲,但我認爲這是對EL規範(LInk to oracle EL spec)爲師,即變量的脅迫爲BigDecimal的,正在做的方式。

代碼的第一行:

${(strutsForm.totalQuota div 1024 div 1024 div 1024)} 

將迫使totalQuota 1024個價值爲BigDecimal,然後進行操作,並返回一個BigDecimal

第二行

${ ((strutsForm.currentUsage div 1024 div 1024) div (totalQuota)) * 100 } 

首先將當前的使用強制爲Double,然後按1024 * 1024進行除法運算,返回Double。這將被強制爲BigDecimal(因爲總額是BigDecimal),然後執行A.divide(B, BigDecimal.ROUND_HALF_UP)。這個輸出的前提取決於BigDecimal變量的大小(影響發生舍入的小數位數)。如果其中任何一個都是0級的,那麼這個舍入將產生一個整數結果,這就是你所看到的(然後乘以100)。

以下普通Java顯示了由步驟和結果上的步驟去

public class jsp_problem_steps 
{ 
    public static void main(String[] args) 
    { 
    Long currentUsage=209715200l; // 209715200l 
    BigDecimal totalQuota = new BigDecimal("343597383680"); // 343597383680 

    BigDecimal coerced = new BigDecimal("1024"); 

    BigDecimal t = totalQuota.divide(coerced, BigDecimal.ROUND_HALF_UP).divide(coerced, BigDecimal.ROUND_HALF_UP).divide(coerced, BigDecimal.ROUND_HALF_UP); 
    System.out.println("coerced BigDecimal quota : " + t); 

    Double d = currentUsage.doubleValue()/1024d/1024d; 

    System.out.println("coerced Double usage : " + d); 

    BigDecimal coerced_d = (new BigDecimal(d)); 

    System.out.println(coerced_d + " at scale " + coerced_d.scale()); 

    BigDecimal res = coerced_d.divide(t,BigDecimal.ROUND_HALF_UP); 

    System.out.println("Result of division : " + res + " THIS IS UNEXPECTED!!!"); 

    res = res.multiply(new BigDecimal("100")); 

    System.out.println("Final value : " + res); 
    } 
} 

給出輸出

coerced BigDecimal quota : 320 
coerced Double usage : 200.0 
200 at scale 0 
Result of division : 1 THIS IS UNEXPECTED!!! 
Final value : 100 

問題的步驟是BigDecimal coerced_d = (new BigDecimal(d));:的兩倍強制爲BigDecimal正在做使用一個BigDecimal構造函數給出一個具有比例尺0的BigDecimal。如果使用BigDecimal coerced_d = (new BigDecimal(d.toString()));來完成構造,那麼您將得到您期望的值(即,作爲分割結果的6225和顯示的62.5)

這是有爭議的,這是否是預期的行爲或一個錯誤 - 從規範不清楚如何強制從一個Double到一個BigDecimal應該完成。

我怎樣才能得到正確的結果?

更改最後一行:

${ ((strutsForm.currentUsage div 1024 div 1024) div (totalQuota.doubleValue())) * 100 } 

應該避免雙爲BigDecimal有問題的脅迫。我不能確定它會工作,因爲我沒有環境來測試,但似乎。