2014-12-04 101 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有问题的胁迫。我不能确定它会工作,因为我没有环境来测试,但似乎。