2013-02-04 4 views
1

문제점 : JSF를 통해 BigDecimal을 형식화해야하지만 JSF는 BigDecimal의 정밀도를 파괴합니다.JSF 부정확 한 BigDecimal 변환

JSF :

<h:outputText value="#{webUtilMB.roundUp(indexPrice.percentage, 2)}"/> 

자바 : WebUtilManagedBean.roundUp 방법에 브레이크 포인트를 갖는

public class IndexPrice { 
    public BigDecimal getPercentage(){ return new BigDecimal("1.325"); } 
} 

@ManagedBean("webUtilMb") 
public class WebUtilManagedBean{ 
    public BigDecimal roundUp(BigDecimal dbvalue, int scale){ 
    return dbvalue.setScale(decimalPlaces, BigDecimal.ROUND_HALF_UP); 
    } 
} 

날 'dbvalue는'1.325 '하지'1.3249999999999999555910790149937383830547332763671875 '이고 보여 주었다. 이 오버로드 된 메서드에 중단 점을 가진 때 나를 놀라게 무엇

public Double roundUp(Double dvalue, int scale){ 
    System.out.println(dvalue); 
} 

했다 :

나는 다음과 WebUtilManagedBean에 검거 방법을 오버로드 - 'dvalue는'1.325 '이고, 올바른이다. - 메서드가 실제로 roundUp (BigDecimal, int) 메서드 대신 호출되었습니다.

나중에 다음과 같은 결과와는 BigDecimal의 생성자 실험 :

BigDecimal db1 = new BigDecimal("1.325"); -> 1.325 
BigDecimal db2 = new BigDecimal(1.325d); -> 1.3249999999999999555910790149937383830547332763671875 

이론 : JSF 더블보다는, 문자열로 변환 내 BigDecimal의 값을 복용했다는 위의에서, 그것은 보인다 값에 새로운 BigDecimal (double)를 호출 해 BigDecimal를 취득 해, 잘못된 값을 돌려줍니다.


수정 :이 문제를 해결하는 한 가지 방법은 다음 코드를 사용하는 것입니다

@ManagedBean("webUtilMb") 
public class WebUtilManagedBean{ 
    public Double roundUp(Double dvalue, int scale){ 
    return this.roundUp(**new BigDecimal(dvalue.toString())**, BigDecimal.ROUND_HALF_UP); 
    } 
    public BigDecimal roundUp(BigDecimal dbvalue, int scale){ 
    return dbvalue.setScale(decimalPlaces, BigDecimal.ROUND_HALF_UP); 
    } 
} 

을하지만 그건 그냥 나에게 해킹처럼 보인다.

수정 사항 및 그 이유에 대한 아이디어. 감사.

답변

2

'둥근'속성이있는 경우 f : convertNumber를 통해 수행하는 것이 가장 이상적이지만 그렇지 않습니다.

이 작업을 수행하는 가장 좋은 방법은 사용자 자신의 roundup f : converter 클래스를 작성하고 EL 메소드 호출 대신 XHTML에서 적절한 경우 f : converter 태그를 사용하는 것입니다. 변환기는 값을 Object, 즉 BigDecimal로 가져오고이를 문자열 자체로 변환합니다. f : converter에 대한 설명서를 참조하십시오. 놀랍게도 JSF는 이것을 올바르게 수행하지 못했지만 일단 EL 메서드 호출을 받으면 모든 것이 String입니다. 이 같은 것 (경고 : 테스트 안 함) :

import java.math.BigDecimal; 
import javax.faces.component.UIComponent; 
import javax.faces.context.FacesContext; 
import javax.faces.convert.Converter; 
import javax.faces.convert.FacesConverter; 

/** 
* Use via e.g.: 
* <pre> 
* &lt;h:outputText value="#{EL}"&gt; 
* &lt;f:converter id="com.edsi.jsf.RoundHalfUp"/&gt; 
* &lt;f:attribute name="decimalPlaces" value="2"/&gt; 
* &lt;/h:outputText&gt; 
* <pre> 
* @author Esmond Pitt 
*/ 
@FacesConverter(value="com.edsi.jsf.RoundHalfUp") 
public class RoundHalfUpConverter implements Converter 
{ 

    @Override 
    public Object getAsObject(FacesContext context, UIComponent component, String value) 
    { 
     throw new UnsupportedOperationException("Not supported yet."); 
    } 

    @Override 
    public String getAsString(FacesContext context, UIComponent component, Object value) 
    { 
     BigDecimal bd = (BigDecimal)value; 
     int decimalPlaces; 
     try 
     { 
      decimalPlaces = Integer.parseInt((String)component.getAttributes().get("decimalPlaces")); 
     } 
     catch (Exception exc) 
     { 
      decimalPlaces = 2; // or whatever 
     } 
     return bd.setScale(decimalPlaces, BigDecimal.ROUND_HALF_UP).toString(); 
    } 

}