View Javadoc
1   package org.nuiton.util;
2   
3   /*
4    * #%L
5    * Nuiton Utils
6    * %%
7    * Copyright (C) 2004 - 2014 CodeLutin
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * #L%
23   */
24  
25  import com.google.common.base.Predicate;
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  
29  import javax.annotation.Nullable;
30  import java.math.BigDecimal;
31  import java.math.MathContext;
32  import java.util.Arrays;
33  
34  /**
35   * @author Kevin Morin - morin@codelutin.com
36   * @since 3.0
37   */
38  public class NumberUtil {
39  
40      /**
41       * Logger.
42       */
43      private static final Log log = LogFactory.getLog(NumberUtil.class);
44  
45      /**
46       * Divide the divisor by the dividend.
47       * Returns an array containing the quotients rounded up or down
48       * to ensure the sum of the quotients equals the divisor.
49       * <p>
50       * e.g. divideAndEnsureSum(100, 3) returns {34, 33, 33}
51       *
52       * @param divisor  the divisor
53       * @param dividend the dividend
54       * @return an array whose length equals dividend
55       */
56      public static int[] divideAndEnsureSum(int divisor, int dividend) {
57          // dividing by 0 is not permitted
58          if (dividend == 0) {
59              return null;
60          }
61  
62          int quotient = (int) ((double) divisor) / dividend;
63          int[] result = new int[dividend];
64          Arrays.fill(result, quotient);
65  
66          int sum = quotient * dividend;
67          int i = 0;
68          while (sum != divisor && i < dividend) {
69              result[i]++;
70              sum++;
71              i++;
72          }
73  
74          return result;
75      }
76  
77      public static final Predicate<Integer> NULL_OR_ZERO_INTEGER = new Predicate<Integer>() {
78  
79          @Override
80          public boolean apply(Integer input) {
81              return input == null || input == 0;
82          }
83  
84          @Override
85          public boolean test(Integer input) {
86              return apply(input);
87          }
88      };
89  
90      public static final Predicate<Float> NULL_OR_ZERO_FLOAT_ONE_DIGIT = new Predicate<Float>() {
91  
92          @Override
93          public boolean apply(Float input) {
94              return input == null || Math.abs(roundOneDigit(input)) < 0.1;
95          }
96  
97          @Override
98          public boolean test(Float input) {
99              return apply(input);
100         }
101     };
102     public static final Predicate<Float> NULL_OR_ZERO_FLOAT_TWO_DIGITS = new Predicate<Float>() {
103 
104         @Override
105         public boolean apply(Float input) {
106             return input == null || Math.abs(roundTwoDigits(input)) < 0.01;
107         }
108 
109         @Override
110         public boolean test(Float input) {
111             return apply(input);
112         }
113     };
114     public static final Predicate<Float> NULL_OR_ZERO_FLOAT_THREE_DIGITS = new Predicate<Float>() {
115 
116         @Override
117         public boolean apply(Float input) {
118             return input == null || Math.abs(roundThreeDigits(input)) < 0.001;
119         }
120 
121         @Override
122         public boolean test(Float input) {
123             return apply(input);
124         }
125     };
126     public static final Predicate<Float> NULL_OR_ZERO_FLOAT_FOUR_DIGITS = new Predicate<Float>() {
127 
128         @Override
129         public boolean apply(Float input) {
130             return input == null || Math.abs(roundFourDigits(input)) < 0.0001;
131         }
132 
133         @Override
134         public boolean test(Float input) {
135             return apply(input);
136         }
137     };
138 
139     public static final Predicate<Float> NULL_OR_ZERO_FLOAT_FIVE_DIGITS = new Predicate<Float>() {
140 
141         @Override
142         public boolean apply(Float input) {
143             return input == null || Math.abs(roundFiveDigits(input)) < 0.00001;
144         }
145 
146         @Override
147         public boolean test(Float input) {
148             return apply(input);
149         }
150     };
151 
152     protected static final MathContext mc1Digit = new MathContext(1);
153     protected static final MathContext mc2Digits = new MathContext(2);
154     protected static final MathContext mc3Digits = new MathContext(3);
155     protected static final MathContext mc4Digits = new MathContext(4);
156     protected static final MathContext mc5Digits = new MathContext(5);
157 
158     public static Float roundOneDigit(Float number) {
159         return round(number, mc1Digit);
160     }
161 
162     public static Float roundTwoDigits(Float number) {
163         return round(number, mc2Digits);
164     }
165 
166     public static Float roundThreeDigits(Float number) {
167         return round(number, mc3Digits);
168     }
169 
170     public static Float roundFourDigits(Float number) {
171         return round(number, mc4Digits);
172     }
173 
174     public static Float roundFiveDigits(Float number) {
175         return round(number, mc5Digits);
176     }
177 
178     public static Float roundNDigits(Float number, int digits) {
179         return round(number, new MathContext(digits));
180     }
181 
182     public static Float round(Float number, MathContext mc) {
183         float old = number;
184         float partieEntier = (int) old;
185         float digit = old - (int) old;
186         number = partieEntier + new BigDecimal(digit).round(mc).floatValue();
187         if (log.isDebugEnabled()) {
188             log.debug("round " + old + " to " + number + " with mc = " + mc);
189         }
190         return number;
191     }
192 
193 }