KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > math > FixedRealFormat


1 // Copyright (c) 1999 Per M.A. Bothner.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

4 package gnu.math;
5 import java.text.FieldPosition JavaDoc;
6
7 // Can't user NumberFormat, because it's format(Object, StringBuffer,
8
// FieldPosition) method is final - and does the wrong thing.
9
// (It ends up converting gnu.math number types to long!)
10

11 /** Format a real number using a fixed-point format.
12  * Used for Common Lisp specs ~F and ~$; also C-style %f.
13  */

14
15 public class FixedRealFormat extends java.text.Format JavaDoc
16 {
17   private int i, d;
18   public int getMaximumFractionDigits() { return d; }
19   public int getMinimumIntegerDigits() { return i; }
20   public void setMaximumFractionDigits(int d) { this.d = d; }
21   public void setMinimumIntegerDigits(int i) { this.i = i; }
22
23   // These should not be public. FIXME.
24
public int width;
25   public int scale;
26   public char padChar;
27   public boolean showPlus;
28   public boolean internalPad;
29   public char overflowChar;
30
31   public void format(RatNum number, boolean negative,
32              StringBuffer JavaDoc sbuf, FieldPosition JavaDoc fpos)
33   {
34     int decimals = getMaximumFractionDigits();
35     int digits;
36     int oldSize = sbuf.length();
37     int signLen = 1;
38     if (negative)
39       sbuf.append('-');
40     else if (showPlus)
41       sbuf.append('+');
42     else
43       signLen = 0;
44     String JavaDoc string;
45     int length;
46     if (decimals < 0)
47       {
48     double val = number.doubleValue();
49     int log = (int) (Math.log(val) / ExponentialFormat.LOG10);
50     int cur_scale = log == 0x80000000 ? 0 : 17 - log;
51     string = RealNum.toScaledInt(val, cur_scale).toString();
52     int i = string.length();
53     digits = i - cur_scale + scale;
54     if (width > 0)
55       decimals = width - signLen - 1 - digits;
56     else
57       decimals = (i > 16 ? 16 : i) - digits;
58     if (decimals < 0)
59       decimals = 0;
60     sbuf.append(string);
61     int digStart = oldSize + signLen;
62     int digEnd = digStart + digits + decimals;
63     i = sbuf.length();
64     char nextDigit;
65     if (digEnd >= i)
66       {
67         digEnd = i;
68         nextDigit = '0';
69       }
70     else
71       nextDigit = sbuf.charAt(digEnd);
72     boolean addOne = nextDigit >= '5';
73     char skip = addOne ? '9' : '0';
74     while (digEnd > digStart + digits && sbuf.charAt(digEnd - 1) == skip)
75       digEnd--;
76     length = digEnd - digStart;
77     decimals = length - digits;
78     if (addOne)
79       {
80         if (ExponentialFormat.addOne(sbuf, digStart, digEnd))
81           {
82         digits++;
83         decimals = 0;
84         length = digits;
85           }
86       }
87     if (decimals == 0 && (width <= 0
88                   || signLen + digits + 1 < width))
89       {
90         decimals = 1;
91         length++;
92         // This is only needed if number==0.0:
93
sbuf.insert(digStart+digits, '0');
94       }
95     sbuf.setLength(digStart + length);
96       }
97     else
98       {
99     string = RealNum.toScaledInt(number, decimals+scale).toString();
100     sbuf.append(string);
101     length = string.length();
102     digits = length - decimals;
103       }
104
105     int total_digits = digits + decimals;
106     // Number of initial zeros to add.
107
int zero_digits = getMinimumIntegerDigits();
108     if (digits >= 0 && digits > zero_digits)
109       zero_digits = 0;
110     else
111       zero_digits -= digits;
112     // If there are no integer digits, add an initial '0', if there is room.
113
if (digits + zero_digits <= 0
114     && (width <= 0 || width > decimals + 1 + signLen))
115       zero_digits++;
116     int needed = signLen + length + zero_digits + 1; /* Add 1 for '.'. */
117     int padding = width - needed;
118     for (int i = zero_digits; --i >= 0; )
119       sbuf.insert(oldSize + signLen, '0');
120     if (padding >= 0)
121       {
122     int i = oldSize;
123     if (internalPad && signLen > 0)
124       i++;
125     while (--padding >= 0)
126       sbuf.insert(i, padChar);
127       }
128     else if (overflowChar != '\0')
129       {
130     sbuf.setLength(oldSize);
131     for (i = width; --i >= 0; )
132       sbuf.append(overflowChar);
133     return;
134      }
135     int newSize = sbuf.length();
136     sbuf.insert(newSize - decimals, '.');
137     /* Requires JDK1.2 FieldPosition extensions:
138     if (fpos == null)
139       {
140     newSize++;
141     if (fpos.getField() == FRACTION_FIELD)
142       {
143         fpos.setBeginIndex(newSize-decimals);
144         fpos.setEndIndex(newSize);
145       }
146     else if (fpos.getField() == INTEGER_FIELD)
147       {
148         fpos.setBeginIndex(newSize-decimals);
149         fpos.setEndIndex(newSize-length-zero_digits-1);
150       }
151       }
152     */

153   }
154
155   public void format(RatNum number, StringBuffer JavaDoc sbuf, FieldPosition JavaDoc fpos)
156   {
157     boolean negative = number.isNegative();
158     if (negative)
159       number = (RatNum) number.rneg();
160     format(number, negative, sbuf, fpos);
161   }
162
163   public void format(RealNum number, StringBuffer JavaDoc sbuf, FieldPosition JavaDoc fpos)
164   {
165     if (number instanceof RatNum)
166       format((RatNum) number, sbuf, fpos);
167     else
168       format(number.doubleValue(), sbuf, fpos);
169   }
170
171   public StringBuffer JavaDoc format(long num, StringBuffer JavaDoc sbuf, FieldPosition JavaDoc fpos)
172   {
173     format(IntNum.make(num), sbuf, fpos);
174     return sbuf;
175   }
176
177   public StringBuffer JavaDoc format(double num, StringBuffer JavaDoc sbuf, FieldPosition JavaDoc fpos)
178   {
179     boolean negative;
180     if (num < 0)
181       {
182     negative = true;
183     num = -num;
184       }
185     else
186       negative = false;
187     format(DFloNum.toExact(num), negative, sbuf, fpos);
188     return sbuf;
189   }
190
191   public StringBuffer JavaDoc format(Object JavaDoc num, StringBuffer JavaDoc sbuf, FieldPosition JavaDoc fpos)
192   {
193     // Common Lisp says if value is non-real, print as if with ~wD. FIXME.
194
return format(((RealNum) num).doubleValue(), sbuf, fpos);
195   }
196
197   public java.lang.Number JavaDoc parse(String JavaDoc text, java.text.ParsePosition JavaDoc status)
198   {
199     throw new Error JavaDoc("RealFixedFormat.parse - not implemented");
200   }
201   public Object JavaDoc parseObject(String JavaDoc text, java.text.ParsePosition JavaDoc status)
202   {
203     throw new Error JavaDoc("RealFixedFormat.parseObject - not implemented");
204   }
205
206 }
207
Popular Tags