View Javadoc
1   package com.github.mygreen.cellformatter.number;
2   
3   
4   /**
5    * 分数を表現するクラス。
6    * <p>POIのSimpleFraction、Commons-MathのFractionを参照。
7    * @author T.TSUCHIE
8    *
9    */
10  public class FractionNumber extends FormattedNumber {
11      
12      /**
13       * 分母の部分
14       */
15      private String denominatorPart;
16      
17      /**
18       * 分子の部分
19       */
20      private String numeratorPart;
21      
22      /**
23       * 帯分数の整数部分
24       */
25      private String wholeNumberPart;
26      
27      /**
28       * 帯分数の形式かどうか。
29       */
30      private boolean wholeType;
31      
32      private FractionNumber(final double value) {
33          super(value);
34          
35      }
36      
37      /**
38       * 分母の値を指定した分数を作成する。その際に、仮分数として作成する。
39       * @param value
40       * @param exactDenom 分母の値
41       * @return
42       */
43      public static FractionNumber createExactDenominator(final double value, int exactDenom) {
44          return createExactDenominator(value, exactDenom, false);
45      }
46      
47      /**
48       * 分母の値を指定した分数を作成する。
49       * @param value
50       * @param exactDenom 分母の値
51       * @param wholeType 'true'のとき帯分数として作成する。'false'のとき仮分数として作成する。
52       * @return
53       */
54      public static FractionNumber createExactDenominator(final double value, int exactDenom, boolean wholeType) {
55          final FractionNumberractionNumber.html#FractionNumber">FractionNumber fractionNumber = new FractionNumber(value);
56          fractionNumber.wholeType = wholeType;
57          
58          final SimpleFraction fraction = SimpleFraction.createFractionExactDenominator(Math.abs(value), exactDenom);
59          setupFractionPart(fraction, fractionNumber);
60          
61          return fractionNumber;
62      }
63      
64      /**
65       * 分母の最大値を指定した分数を作成する。その際に、仮分数として作成する。
66       * @param value
67       * @param maxDenom
68       * @return
69       */
70      public static FractionNumber createMaxDenominator(final double value, int maxDenom) {
71          return createMaxDenominator(value, maxDenom, false);
72      }
73      
74      /**
75       * 分母の最大値を指定した分数を作成する。
76       * @param value
77       * @param maxDenom 分母の最大値。
78       * @param wholeType 'true'のとき帯分数として作成する。'false'のとき仮分数として作成する。
79       * @return
80       */
81      public static FractionNumber createMaxDenominator(final double value, int maxDenom, boolean wholeType) {
82          final FractionNumberractionNumber.html#FractionNumber">FractionNumber fractionNumber = new FractionNumber(value);
83          fractionNumber.wholeType = wholeType;
84          
85          final SimpleFraction fraction = SimpleFraction.createFractionMaxDenominator(Math.abs(value), maxDenom);
86          setupFractionPart(fraction, fractionNumber);
87          
88          return fractionNumber;
89      }
90      
91      /**
92       * 分数の各部品を設定する
93       * @param fraction
94       * @param fractionNumber
95       */
96      private static void setupFractionPart(final SimpleFraction fraction, final FractionNumber fractionNumber) {
97          
98          fractionNumber.denominatorPart = String.valueOf(fraction.getDenominator());
99          
100         if(fractionNumber.isWholeType()) {
101             int wholeNumber = fraction.getNumerator() / fraction.getDenominator();
102             fractionNumber.wholeNumberPart = wholeNumber == 0 ? "" : String.valueOf(wholeNumber);
103             
104             int numerator = fraction.getNumerator() % fraction.getDenominator();
105             fractionNumber.numeratorPart = String.valueOf(numerator);
106             
107         } else {
108             fractionNumber.wholeNumberPart = "";
109             fractionNumber.numeratorPart = String.valueOf(fraction.getNumerator());
110             
111         }
112     }
113     
114     /**
115      * 帯分数の形式かどうか。
116      * @return
117      */
118     public boolean isWholeType() {
119         return wholeType;
120     }
121     
122     /**
123      * 分母の部分を取得する。
124      * @return
125      */
126     public String getDenominatorPart() {
127         return denominatorPart;
128     }
129     
130     /**
131      * 分母の指定した桁の値を取得する。
132      * @param digit 1から始まる
133      * @return 存在しない桁の場合は空文字を返す。
134      */
135     public String getDenominatorPart(final int digit) {
136         
137         final int length = denominatorPart.length();
138         if(length < digit || digit <= 0) {
139             return "";
140         }
141         
142         return String.valueOf(denominatorPart.charAt(length - digit));
143     }
144     
145     /**
146      * 分母の指定した桁以降の値を取得する。
147      * @param digit 1から始まる
148      * @return 存在しない桁の場合は空文字を返す。
149      */
150     public String getDenominatorPartAfter(final int digit) {
151         
152         final int length = denominatorPart.length();
153         if(length < digit || digit <= 0) {
154             return "";
155         }
156         
157         return denominatorPart.substring(0, (length - digit + 1));
158     }
159     
160     /**
161      * 分子の部分を取得する
162      * @return
163      */
164     public String getNumeratorPart() {
165         return numeratorPart;
166     }
167     
168     /**
169      * 分子の指定した桁の値を取得する。
170      * @param digit 1から始まる
171      * @return 存在しない桁の場合は空文字を返す。
172      */
173     public String getNumeratorPart(final int digit) {
174         
175         final int length = numeratorPart.length();
176         if(length < digit || digit <= 0) {
177             return "";
178         }
179         
180         return String.valueOf(numeratorPart.charAt(length - digit));
181     }
182     
183     /**
184      * 分子の指定した桁以降の値を取得する。
185      * @param digit 1から始まる
186      * @return 存在しない桁の場合は空文字を返す。
187      */
188     public String getNumeratorPartAfter(final int digit) {
189         
190         final int length = numeratorPart.length();
191         if(length < digit || digit <= 0) {
192             return "";
193         }
194         
195         return numeratorPart.substring(0, (length - digit + 1));
196     }
197     
198     /**
199      * 帯分数の整数部分を取得する。
200      * <p>整数部分が0または帯分数出ない場合は、空文字を返す。
201      * @return
202      */
203     public String getWholeNumberPart() {
204         return wholeNumberPart;
205     }
206     
207     /**
208      * 帯分数の整数部分の指定した桁の値を取得する。
209      * @param digit 1から始まる
210      * @return 存在しない桁の場合は空文字を返す。
211      */
212     public String getWholeNumberPart(final int digit) {
213         
214         final int length = wholeNumberPart.length();
215         if(length < digit || digit <= 0) {
216             return "";
217         }
218         
219         return String.valueOf(wholeNumberPart.charAt(length - digit));
220     }
221     
222     /**
223      * 帯分数の整数部分の指定した桁以降の値を取得する。
224      * @param digit 1から始まる
225      * @return 存在しない桁の場合は空文字を返す。
226      */
227     public String getWholeNumberPartAfter(final int digit) {
228         
229         final int length = wholeNumberPart.length();
230         if(length < digit || digit <= 0) {
231             return "";
232         }
233         
234         return wholeNumberPart.substring(0, (length - digit + 1));
235     }
236     
237     @Override
238     public String toString() {
239         
240         if(isZero()) {
241             return "0";
242         }
243         
244         StringBuilder sb = new StringBuilder();
245         
246         if(isNegative()) {
247             sb.append("-");
248         }
249         
250         if(isWholeType() && !getWholeNumberPart().isEmpty()) {
251             sb.append(getWholeNumberPart()).append(" ");
252         }
253         
254         sb.append(getNumeratorPart()).append("/").append(getDenominatorPart());
255         
256         return sb.toString();
257         
258     }
259     
260 }