001    /**
002     * =========================================
003     * LibFormula : a free Java formula library
004     * =========================================
005     *
006     * Project Info:  http://reporting.pentaho.org/libformula/
007     *
008     * (C) Copyright 2006-2007, by Pentaho Corporation and Contributors.
009     *
010     * This library is free software; you can redistribute it and/or modify it under the terms
011     * of the GNU Lesser General Public License as published by the Free Software Foundation;
012     * either version 2.1 of the License, or (at your option) any later version.
013     *
014     * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
015     * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016     * See the GNU Lesser General Public License for more details.
017     *
018     * You should have received a copy of the GNU Lesser General Public License along with this
019     * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020     * Boston, MA 02111-1307, USA.
021     *
022     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
023     * in the United States and other countries.]
024     *
025     *
026     * ------------
027     * $Id: NumberUtil.java 3522 2007-10-16 10:56:57Z tmorgner $
028     * ------------
029     * (C) Copyright 2006-2007, by Pentaho Corporation.
030     */
031    
032    package org.jfree.formula.util;
033    
034    import java.math.BigDecimal;
035    
036    import org.jfree.formula.EvaluationException;
037    import org.jfree.formula.LibFormulaErrorValue;
038    
039    public class NumberUtil
040    {
041      public static final BigDecimal DELTA = new BigDecimal("0.000000000000000000000000000005");
042    
043      private NumberUtil()
044      {
045      }
046    
047      public static BigDecimal getAsBigDecimal(final Number number) throws EvaluationException
048      {
049        if (number == null)
050        {
051          throw new EvaluationException(
052              LibFormulaErrorValue.ERROR_INVALID_ARGUMENT_VALUE);
053        }
054        
055        if(number instanceof BigDecimal)
056        {
057          return (BigDecimal)number;
058        }
059        else
060        {
061          return new BigDecimal(number.toString());
062        }
063      }
064      
065      public static Integer performIntRounding(BigDecimal n)
066      {
067    
068        try
069        {
070          // no need to go further if the value is already an integer
071          n = n.setScale(0);
072          return new Integer(n.intValue());
073        }
074        catch(ArithmeticException e)
075        {
076          //ignore and continue
077        }
078        
079        final BigDecimal round;
080        if(n.signum()<0)
081        {
082          n = n.subtract(DELTA);
083          round = n.setScale(0, BigDecimal.ROUND_UP);
084        }
085        else
086        {
087          n = n.add(DELTA);
088          round = n.setScale(1, BigDecimal.ROUND_DOWN);
089        }
090        return new Integer(round.intValue());
091      }
092      
093      public static BigDecimal removeTrailingZeros(BigDecimal bd)
094      {
095        if(bd.signum() == 0)
096        {
097          return bd.setScale(0);
098        }
099    
100        // Todo: This approach is very expensive. There must be a better way ...
101        try
102        {
103          while(true)
104          {
105            final int scale = bd.scale();
106            if (scale == 0)
107            {
108              return bd;
109            }
110            bd = bd.setScale(scale-1);
111          }
112        }
113        catch(ArithmeticException ae)
114        {
115          return bd;
116        }
117      }
118    }