왜 이런 일이 발생합니까?
는
이 카운터 직관 동작이지만, I는 즉,의 BigDecimal에 변수 강제 분할에 대한 EL 사양 (LInk to oracle EL spec)는, 수행되는 방식이다라고 생각한다.
코드의 첫 번째 줄 :
${(strutsForm.totalQuota div 1024 div 1024 div 1024)}
번째 행을 BigDecimal를
을 totalQuota에게 BigDecimal를 행 1024의 값을 강요하고 반환하는 동작을 수행한다
${ ((strutsForm.currentUsage div 1024 div 1024) div (totalQuota)) * 100 }
것 먼저 currentUsage를 Double에 강요하고 1024 * 1024로 나누어 Double을 반환합니다. BigDecimal에 강요 (totalQuota가 BigDecimal이기 (위해) 때문에, A.divide(B, BigDecimal.ROUND_HALF_UP)
를 실행한다). 이것의 결과는, BigDecimal 변수의 스케일에 의존합니다 (소수점 이하 자리 올림에 영향을줍니다). 둘 중 하나가 스케일 0이면이 반올림은 사용자가보고있는 정수 결과 (100을 곱한 값)가됩니다.
다음 일반 자바 단계와 결과에 의해 단계에 무슨 일이 일어나고 있는지 보여줍니다
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를 더블의 강제 수행되고 규모가 0 인 BigDecimal을 제공하는 BigDecimal 생성자를 사용합니다. 예를 들어 BigDecimal coerced_d = (new BigDecimal(d.toString()));
을 사용하여 구성을 완료 한 경우 예상되는 값을 얻을 수 있습니다 (즉, 나누기의 결과로 0.625가 표시되고 62.5가 표시됨)
이것이 예상되는 동작인지 버그인지는 논란의 여지가 있습니다. Double에서 BigDecimal로 강제 변환하는 방법을 사양에서 분명히 알 수 없습니다.
어떻게하면 적절한 결과를 얻을 수 있습니까?
변경 마지막 줄에 :을 BigDecimal에 더블의 문제 강압을 피해야한다
${ ((strutsForm.currentUsage div 1024 div 1024) div (totalQuota.doubleValue())) * 100 }
. 나는 시험 할 환경이 없기 때문에 그것이 작동 할 것이라고 확신 할 수는 없지만, 그렇게 보인다.
내가 가장 쉬운 해결책은 바로 서버 측에서이 계산을하고보기 페이지에서 결과를 사용하는 것입니다 생각합니다. –
@SemihEker : 당신 말이 맞아요. 하지만 jsp에서도 할 수 있는지를 찾고 있습니다. –