]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | /* |
2 | ********************************************************************** | |
73c04bcf | 3 | * Copyright (C) 1997-2005, International Business Machines |
b75a7d8f A |
4 | * Corporation and others. All Rights Reserved. |
5 | ********************************************************************** | |
6 | * | |
7 | * File DIGITLST.CPP | |
8 | * | |
9 | * Modification History: | |
10 | * | |
11 | * Date Name Description | |
12 | * 03/21/97 clhuang Converted from java. | |
13 | * 03/21/97 clhuang Implemented with new APIs. | |
14 | * 03/27/97 helena Updated to pass the simple test after code review. | |
15 | * 03/31/97 aliu Moved isLONG_MIN to here, and fixed it. | |
16 | * 04/15/97 aliu Changed MAX_COUNT to DBL_DIG. Changed Digit to char. | |
17 | * Reworked representation by replacing fDecimalAt | |
18 | * with fExponent. | |
19 | * 04/16/97 aliu Rewrote set() and getDouble() to use sprintf/atof | |
20 | * to do digit conversion. | |
21 | * 09/09/97 aliu Modified for exponential notation support. | |
22 | * 08/02/98 stephen Added nearest/even rounding | |
23 | * Fixed bug in fitsIntoLong | |
24 | ****************************************************************************** | |
25 | */ | |
26 | ||
27 | #include "unicode/putil.h" | |
28 | #include "digitlst.h" | |
374ca955 A |
29 | #include "cstring.h" |
30 | #include "putilimp.h" | |
b75a7d8f A |
31 | #include <stdlib.h> |
32 | #include <limits.h> | |
33 | #include <string.h> | |
34 | #include <stdio.h> | |
35 | ||
36 | // *************************************************************************** | |
37 | // class DigitList | |
38 | // This class handles the transcoding between numeric values and strings of | |
39 | // characters. Only handles as non-negative numbers. | |
40 | // *************************************************************************** | |
41 | ||
42 | /** | |
43 | * This is the zero digit. Array elements fDigits[i] have values from | |
44 | * kZero to kZero + 9. Typically, this is '0'. | |
45 | */ | |
46 | #define kZero '0' | |
47 | ||
48 | static char gDecimal = 0; | |
49 | ||
50 | /* Only for 32 bit numbers. Ignore the negative sign. */ | |
51 | static const char LONG_MIN_REP[] = "2147483648"; | |
374ca955 A |
52 | static const char I64_MIN_REP[] = "9223372036854775808"; |
53 | ||
b75a7d8f | 54 | enum { |
374ca955 A |
55 | LONG_MIN_REP_LENGTH = sizeof(LONG_MIN_REP) - 1, //Ignore the NULL at the end |
56 | I64_MIN_REP_LENGTH = sizeof(I64_MIN_REP) - 1 //Ignore the NULL at the end | |
b75a7d8f A |
57 | }; |
58 | ||
59 | U_NAMESPACE_BEGIN | |
60 | ||
61 | ||
62 | // ------------------------------------- | |
63 | // default constructor | |
64 | ||
65 | DigitList::DigitList() | |
66 | { | |
374ca955 | 67 | fDigits = fDecimalDigits + 1; // skip the decimal |
b75a7d8f A |
68 | clear(); |
69 | } | |
70 | ||
71 | // ------------------------------------- | |
72 | ||
73 | DigitList::~DigitList() | |
74 | { | |
75 | } | |
76 | ||
77 | // ------------------------------------- | |
78 | // copy constructor | |
79 | ||
80 | DigitList::DigitList(const DigitList &other) | |
81 | { | |
82 | fDigits = fDecimalDigits + 1; // skip the decimal | |
83 | *this = other; | |
84 | } | |
85 | ||
86 | // ------------------------------------- | |
87 | // assignment operator | |
88 | ||
89 | DigitList& | |
90 | DigitList::operator=(const DigitList& other) | |
91 | { | |
92 | if (this != &other) | |
93 | { | |
94 | fDecimalAt = other.fDecimalAt; | |
95 | fCount = other.fCount; | |
96 | fIsPositive = other.fIsPositive; | |
03115e54 | 97 | fRoundingMode = other.fRoundingMode; |
374ca955 | 98 | uprv_strncpy(fDigits, other.fDigits, fCount); |
b75a7d8f A |
99 | } |
100 | return *this; | |
101 | } | |
102 | ||
103 | // ------------------------------------- | |
104 | ||
105 | UBool | |
106 | DigitList::operator==(const DigitList& that) const | |
107 | { | |
108 | return ((this == &that) || | |
109 | (fDecimalAt == that.fDecimalAt && | |
110 | fCount == that.fCount && | |
111 | fIsPositive == that.fIsPositive && | |
03115e54 | 112 | fRoundingMode == that.fRoundingMode && |
374ca955 | 113 | uprv_strncmp(fDigits, that.fDigits, fCount) == 0)); |
b75a7d8f A |
114 | } |
115 | ||
116 | // ------------------------------------- | |
117 | // Resets the digit list; sets all the digits to zero. | |
118 | ||
119 | void | |
120 | DigitList::clear() | |
121 | { | |
b75a7d8f A |
122 | fDecimalAt = 0; |
123 | fCount = 0; | |
124 | fIsPositive = TRUE; | |
03115e54 | 125 | fRoundingMode = DecimalFormat::kRoundHalfEven; |
b75a7d8f A |
126 | |
127 | // Don't bother initializing fDigits because fCount is 0. | |
128 | } | |
129 | ||
130 | ||
131 | ||
132 | // ------------------------------------- | |
133 | ||
134 | /** | |
135 | * Formats a number into a base 10 string representation, and NULL terminates it. | |
136 | * @param number The number to format | |
137 | * @param outputStr The string to output to | |
138 | * @param outputLen The maximum number of characters to put into outputStr | |
139 | * (including NULL). | |
140 | * @return the number of digits written, not including the sign. | |
141 | */ | |
142 | static int32_t | |
374ca955 | 143 | formatBase10(int64_t number, char *outputStr, int32_t outputLen) |
b75a7d8f A |
144 | { |
145 | char buffer[MAX_DIGITS + 1]; | |
146 | int32_t bufferLen; | |
374ca955 | 147 | int32_t result; |
b75a7d8f A |
148 | |
149 | if (outputLen > MAX_DIGITS) { | |
150 | outputLen = MAX_DIGITS; // Ignore NULL | |
151 | } | |
152 | else if (outputLen < 3) { | |
153 | return 0; // Not enough room | |
154 | } | |
155 | ||
156 | bufferLen = outputLen; | |
157 | ||
158 | if (number < 0) { // Negative numbers are slightly larger than a postive | |
159 | buffer[bufferLen--] = (char)(-(number % 10) + kZero); | |
160 | number /= -10; | |
161 | *(outputStr++) = '-'; | |
162 | } | |
163 | else { | |
164 | *(outputStr++) = '+'; // allow +0 | |
165 | } | |
166 | while (bufferLen >= 0 && number) { // Output the number | |
167 | buffer[bufferLen--] = (char)(number % 10 + kZero); | |
168 | number /= 10; | |
169 | } | |
170 | ||
374ca955 | 171 | result = outputLen - bufferLen++; |
b75a7d8f | 172 | |
374ca955 | 173 | while (bufferLen <= outputLen) { // Copy the number to output |
b75a7d8f A |
174 | *(outputStr++) = buffer[bufferLen++]; |
175 | } | |
176 | *outputStr = 0; // NULL terminate. | |
374ca955 | 177 | return result; |
b75a7d8f A |
178 | } |
179 | ||
180 | /** | |
181 | * Currently, getDouble() depends on atof() to do its conversion. | |
182 | * | |
183 | * WARNING!! | |
184 | * This is an extremely costly function. ~1/2 of the conversion time | |
185 | * can be linked to this function. | |
186 | */ | |
187 | double | |
374ca955 | 188 | DigitList::getDouble() /*const*/ |
b75a7d8f A |
189 | { |
190 | double value; | |
191 | ||
192 | if (fCount == 0) { | |
193 | value = 0.0; | |
194 | } | |
195 | else { | |
374ca955 | 196 | char* end = NULL; |
b75a7d8f A |
197 | if (!gDecimal) { |
198 | char rep[MAX_DIGITS]; | |
199 | // For machines that decide to change the decimal on you, | |
200 | // and try to be too smart with localization. | |
201 | // This normally should be just a '.'. | |
202 | sprintf(rep, "%+1.1f", 1.0); | |
203 | gDecimal = rep[2]; | |
204 | } | |
205 | ||
206 | *fDecimalDigits = gDecimal; | |
207 | *(fDigits+fCount) = 'e'; // add an e after the digits. | |
208 | formatBase10(fDecimalAt, | |
209 | fDigits + fCount + 1, // skip the 'e' | |
210 | MAX_DEC_DIGITS - fCount - 3); // skip the 'e' and '.' | |
374ca955 | 211 | value = uprv_strtod(fDecimalDigits, &end); |
b75a7d8f A |
212 | } |
213 | ||
214 | return fIsPositive ? value : -value; | |
215 | } | |
216 | ||
217 | // ------------------------------------- | |
218 | ||
219 | /** | |
220 | * Make sure that fitsIntoLong() is called before calling this function. | |
221 | */ | |
374ca955 | 222 | int32_t DigitList::getLong() /*const*/ |
b75a7d8f A |
223 | { |
224 | if (fCount == fDecimalAt) { | |
225 | int32_t value; | |
226 | ||
227 | fDigits[fCount] = 0; // NULL terminate | |
228 | ||
229 | // This conversion is bad on 64-bit platforms when we want to | |
230 | // be able to return a 64-bit number [grhoten] | |
231 | *fDecimalDigits = fIsPositive ? '+' : '-'; | |
232 | value = (int32_t)atol(fDecimalDigits); | |
233 | return value; | |
234 | } | |
235 | else { | |
236 | // This is 100% accurate in c++ because if we are representing | |
237 | // an integral value, we suffer nothing in the conversion to | |
238 | // double. If we are to support 64-bit longs later, getLong() | |
239 | // must be rewritten. [LIU] | |
240 | return (int32_t)getDouble(); | |
241 | } | |
242 | } | |
243 | ||
374ca955 A |
244 | |
245 | /** | |
246 | * Make sure that fitsIntoInt64() is called before calling this function. | |
247 | */ | |
248 | int64_t DigitList::getInt64() /*const*/ | |
249 | { | |
250 | if (fCount == fDecimalAt) { | |
251 | uint64_t value; | |
252 | ||
253 | fDigits[fCount] = 0; // NULL terminate | |
254 | ||
255 | // This conversion is bad on 64-bit platforms when we want to | |
256 | // be able to return a 64-bit number [grhoten] | |
257 | *fDecimalDigits = fIsPositive ? '+' : '-'; | |
258 | ||
259 | if (fCount < LONG_MIN_REP_LENGTH) { | |
260 | return (int64_t)atol(fDecimalDigits); | |
261 | } | |
262 | ||
263 | // too big for atol, hand-roll atoi64 | |
264 | value = 0; | |
265 | for (int i = 0; i < fCount; ++i) { | |
266 | int v = fDigits[i] - kZero; | |
267 | value = value * (uint64_t)10 + (uint64_t)v; | |
268 | } | |
269 | if (!fIsPositive) { | |
270 | value = ~value; | |
271 | value += 1; | |
272 | } | |
273 | int64_t svalue = (int64_t)value; | |
274 | return svalue; | |
275 | } | |
276 | else { | |
277 | // todo: figure out best approach | |
278 | ||
279 | // This is 100% accurate in c++ because if we are representing | |
280 | // an integral value, we suffer nothing in the conversion to | |
281 | // double. If we are to support 64-bit longs later, getLong() | |
282 | // must be rewritten. [LIU] | |
283 | return (int64_t)getDouble(); | |
284 | } | |
285 | } | |
286 | ||
b75a7d8f A |
287 | /** |
288 | * Return true if the number represented by this object can fit into | |
289 | * a long. | |
290 | */ | |
291 | UBool | |
374ca955 | 292 | DigitList::fitsIntoLong(UBool ignoreNegativeZero) /*const*/ |
b75a7d8f A |
293 | { |
294 | // Figure out if the result will fit in a long. We have to | |
295 | // first look for nonzero digits after the decimal point; | |
374ca955 | 296 | // then check the size. |
b75a7d8f A |
297 | |
298 | // Trim trailing zeros after the decimal point. This does not change | |
299 | // the represented value. | |
300 | while (fCount > fDecimalAt && fCount > 0 && fDigits[fCount - 1] == kZero) | |
301 | --fCount; | |
302 | ||
303 | if (fCount == 0) { | |
304 | // Positive zero fits into a long, but negative zero can only | |
305 | // be represented as a double. - bug 4162852 | |
306 | return fIsPositive || ignoreNegativeZero; | |
307 | } | |
308 | ||
b75a7d8f A |
309 | // If the digit list represents a double or this number is too |
310 | // big for a long. | |
311 | if (fDecimalAt < fCount || fDecimalAt > LONG_MIN_REP_LENGTH) | |
312 | return FALSE; | |
313 | ||
314 | // If number is small enough to fit in a long | |
315 | if (fDecimalAt < LONG_MIN_REP_LENGTH) | |
316 | return TRUE; | |
317 | ||
318 | // At this point we have fDecimalAt == fCount, and fCount == LONG_MIN_REP_LENGTH. | |
319 | // The number will overflow if it is larger than LONG_MAX | |
320 | // or smaller than LONG_MIN. | |
321 | for (int32_t i=0; i<fCount; ++i) | |
322 | { | |
323 | char dig = fDigits[i], | |
324 | max = LONG_MIN_REP[i]; | |
325 | if (dig > max) | |
326 | return FALSE; | |
327 | if (dig < max) | |
328 | return TRUE; | |
329 | } | |
330 | ||
331 | // At this point the first count digits match. If fDecimalAt is less | |
332 | // than count, then the remaining digits are zero, and we return true. | |
333 | if (fCount < fDecimalAt) | |
334 | return TRUE; | |
335 | ||
336 | // Now we have a representation of Long.MIN_VALUE, without the leading | |
337 | // negative sign. If this represents a positive value, then it does | |
338 | // not fit; otherwise it fits. | |
339 | return !fIsPositive; | |
340 | } | |
341 | ||
374ca955 A |
342 | /** |
343 | * Return true if the number represented by this object can fit into | |
344 | * a long. | |
345 | */ | |
346 | UBool | |
347 | DigitList::fitsIntoInt64(UBool ignoreNegativeZero) /*const*/ | |
348 | { | |
349 | // Figure out if the result will fit in a long. We have to | |
350 | // first look for nonzero digits after the decimal point; | |
351 | // then check the size. | |
352 | ||
353 | // Trim trailing zeros after the decimal point. This does not change | |
354 | // the represented value. | |
355 | while (fCount > fDecimalAt && fCount > 0 && fDigits[fCount - 1] == kZero) | |
356 | --fCount; | |
357 | ||
358 | if (fCount == 0) { | |
359 | // Positive zero fits into a long, but negative zero can only | |
360 | // be represented as a double. - bug 4162852 | |
361 | return fIsPositive || ignoreNegativeZero; | |
362 | } | |
363 | ||
364 | // If the digit list represents a double or this number is too | |
365 | // big for a long. | |
366 | if (fDecimalAt < fCount || fDecimalAt > I64_MIN_REP_LENGTH) | |
367 | return FALSE; | |
368 | ||
369 | // If number is small enough to fit in an int64 | |
370 | if (fDecimalAt < I64_MIN_REP_LENGTH) | |
371 | return TRUE; | |
372 | ||
373 | // At this point we have fDecimalAt == fCount, and fCount == INT64_MIN_REP_LENGTH. | |
374 | // The number will overflow if it is larger than U_INT64_MAX | |
375 | // or smaller than U_INT64_MIN. | |
376 | for (int32_t i=0; i<fCount; ++i) | |
377 | { | |
378 | char dig = fDigits[i], | |
379 | max = I64_MIN_REP[i]; | |
380 | if (dig > max) | |
381 | return FALSE; | |
382 | if (dig < max) | |
383 | return TRUE; | |
384 | } | |
385 | ||
386 | // At this point the first count digits match. If fDecimalAt is less | |
387 | // than count, then the remaining digits are zero, and we return true. | |
388 | if (fCount < fDecimalAt) | |
389 | return TRUE; | |
390 | ||
391 | // Now we have a representation of INT64_MIN_VALUE, without the leading | |
392 | // negative sign. If this represents a positive value, then it does | |
393 | // not fit; otherwise it fits. | |
394 | return !fIsPositive; | |
395 | } | |
396 | ||
397 | ||
b75a7d8f A |
398 | // ------------------------------------- |
399 | ||
374ca955 A |
400 | void |
401 | DigitList::set(int32_t source, int32_t maximumDigits) | |
402 | { | |
403 | set((int64_t)source, maximumDigits); | |
404 | } | |
405 | ||
406 | // ------------------------------------- | |
b75a7d8f A |
407 | /** |
408 | * @param maximumDigits The maximum digits to be generated. If zero, | |
409 | * there is no maximum -- generate all digits. | |
410 | */ | |
411 | void | |
374ca955 | 412 | DigitList::set(int64_t source, int32_t maximumDigits) |
b75a7d8f A |
413 | { |
414 | fCount = fDecimalAt = formatBase10(source, fDecimalDigits, MAX_DIGITS); | |
415 | ||
416 | fIsPositive = (*fDecimalDigits == '+'); | |
417 | ||
418 | // Don't copy trailing zeros | |
419 | while (fCount > 1 && fDigits[fCount - 1] == kZero) | |
420 | --fCount; | |
421 | ||
422 | if(maximumDigits > 0) | |
423 | round(maximumDigits); | |
424 | } | |
425 | ||
426 | /** | |
427 | * Set the digit list to a representation of the given double value. | |
428 | * This method supports both fixed-point and exponential notation. | |
429 | * @param source Value to be converted; must not be Inf, -Inf, Nan, | |
430 | * or a value <= 0. | |
431 | * @param maximumDigits The most fractional or total digits which should | |
432 | * be converted. If total digits, and the value is zero, then | |
433 | * there is no maximum -- generate all digits. | |
434 | * @param fixedPoint If true, then maximumDigits is the maximum | |
435 | * fractional digits to be converted. If false, total digits. | |
436 | */ | |
437 | void | |
438 | DigitList::set(double source, int32_t maximumDigits, UBool fixedPoint) | |
439 | { | |
440 | // for now, simple implementation; later, do proper IEEE stuff | |
441 | char rep[MAX_DIGITS + 8]; // Extra space for '+', '.', e+NNN, and '\0' (actually +8 is enough) | |
442 | char *digitPtr = fDigits; | |
443 | char *repPtr = rep + 2; // +2 to skip the sign and decimal | |
444 | int32_t exponent = 0; | |
445 | ||
446 | fIsPositive = !uprv_isNegative(source); // Allow +0 and -0 | |
447 | ||
448 | // Generate a representation of the form /[+-][0-9]+e[+-][0-9]+/ | |
374ca955 | 449 | sprintf(rep, "%+1.*e", MAX_DBL_DIGITS - 1, source); |
b75a7d8f A |
450 | fDecimalAt = 0; |
451 | rep[2] = rep[1]; // remove decimal | |
452 | ||
453 | while (*repPtr == kZero) { | |
454 | repPtr++; | |
455 | fDecimalAt--; // account for leading zeros | |
456 | } | |
457 | ||
458 | while (*repPtr != 'e') { | |
459 | *(digitPtr++) = *(repPtr++); | |
460 | } | |
374ca955 | 461 | fCount = MAX_DBL_DIGITS + fDecimalAt; |
b75a7d8f A |
462 | |
463 | // Parse an exponent of the form /[eE][+-][0-9]+/ | |
464 | UBool negExp = (*(++repPtr) == '-'); | |
465 | while (*(++repPtr) != 0) { | |
466 | exponent = 10*exponent + *repPtr - kZero; | |
467 | } | |
468 | if (negExp) { | |
469 | exponent = -exponent; | |
470 | } | |
471 | fDecimalAt += exponent + 1; // +1 for decimal removal | |
472 | ||
473 | // The negative of the exponent represents the number of leading | |
474 | // zeros between the decimal and the first non-zero digit, for | |
475 | // a value < 0.1 (e.g., for 0.00123, -decimalAt == 2). If this | |
476 | // is more than the maximum fraction digits, then we have an underflow | |
477 | // for the printed representation. | |
478 | if (fixedPoint && -fDecimalAt >= maximumDigits) | |
479 | { | |
480 | // If we round 0.0009 to 3 fractional digits, then we have to | |
481 | // create a new one digit in the least significant location. | |
482 | if (-fDecimalAt == maximumDigits && shouldRoundUp(0)) { | |
483 | fCount = 1; | |
484 | ++fDecimalAt; | |
485 | fDigits[0] = (char)'1'; | |
486 | } else { | |
487 | // Handle an underflow to zero when we round something like | |
488 | // 0.0009 to 2 fractional digits. | |
489 | fCount = 0; | |
490 | } | |
491 | return; | |
492 | } | |
493 | ||
494 | ||
495 | // Eliminate digits beyond maximum digits to be displayed. | |
496 | // Round up if appropriate. Do NOT round in the special | |
497 | // case where maximumDigits == 0 and fixedPoint is FALSE. | |
498 | if (fixedPoint || (0 < maximumDigits && maximumDigits < fCount)) { | |
499 | round(fixedPoint ? (maximumDigits + fDecimalAt) : maximumDigits); | |
500 | } | |
501 | else { | |
502 | // Eliminate trailing zeros. | |
503 | while (fCount > 1 && fDigits[fCount - 1] == kZero) | |
504 | --fCount; | |
505 | } | |
506 | } | |
507 | ||
508 | // ------------------------------------- | |
509 | ||
510 | /** | |
511 | * Round the representation to the given number of digits. | |
512 | * @param maximumDigits The maximum number of digits to be shown. | |
513 | * Upon return, count will be less than or equal to maximumDigits. | |
514 | */ | |
515 | void | |
516 | DigitList::round(int32_t maximumDigits) | |
517 | { | |
518 | // Eliminate digits beyond maximum digits to be displayed. | |
519 | // Round up if appropriate. | |
520 | if (maximumDigits >= 0 && maximumDigits < fCount) | |
521 | { | |
522 | if (shouldRoundUp(maximumDigits)) { | |
523 | // Rounding up involved incrementing digits from LSD to MSD. | |
524 | // In most cases this is simple, but in a worst case situation | |
525 | // (9999..99) we have to adjust the decimalAt value. | |
526 | while (--maximumDigits >= 0 && ++fDigits[maximumDigits] > '9') | |
527 | ; | |
528 | ||
529 | if (maximumDigits < 0) | |
530 | { | |
531 | // We have all 9's, so we increment to a single digit | |
532 | // of one and adjust the exponent. | |
533 | fDigits[0] = (char) '1'; | |
534 | ++fDecimalAt; | |
535 | maximumDigits = 1; // Adjust the count | |
536 | } | |
537 | else | |
538 | { | |
539 | ++maximumDigits; // Increment for use as count | |
540 | } | |
541 | } | |
542 | fCount = maximumDigits; | |
543 | } | |
544 | ||
545 | // Eliminate trailing zeros. | |
546 | while (fCount > 1 && fDigits[fCount-1] == kZero) { | |
547 | --fCount; | |
548 | } | |
549 | } | |
550 | ||
551 | /** | |
552 | * Return true if truncating the representation to the given number | |
553 | * of digits will result in an increment to the last digit. This | |
03115e54 | 554 | * method implements the requested rounding mode. |
b75a7d8f A |
555 | * [bnf] |
556 | * @param maximumDigits the number of digits to keep, from 0 to | |
557 | * <code>count-1</code>. If 0, then all digits are rounded away, and | |
558 | * this method returns true if a one should be generated (e.g., formatting | |
559 | * 0.09 with "#.#"). | |
560 | * @return true if digit <code>maximumDigits-1</code> should be | |
561 | * incremented | |
562 | */ | |
374ca955 | 563 | UBool DigitList::shouldRoundUp(int32_t maximumDigits) const { |
03115e54 A |
564 | switch (fRoundingMode) { |
565 | case DecimalFormat::kRoundCeiling: | |
566 | return fIsPositive; | |
567 | case DecimalFormat::kRoundFloor: | |
568 | return !fIsPositive; | |
569 | case DecimalFormat::kRoundDown: | |
570 | return FALSE; | |
571 | case DecimalFormat::kRoundUp: | |
572 | return TRUE; | |
573 | case DecimalFormat::kRoundHalfEven: | |
574 | case DecimalFormat::kRoundHalfDown: | |
575 | case DecimalFormat::kRoundHalfUp: | |
576 | default: | |
577 | if (fDigits[maximumDigits] == '5' ) { | |
578 | for (int i=maximumDigits+1; i<fCount; ++i) { | |
579 | if (fDigits[i] != kZero) { | |
580 | return TRUE; | |
581 | } | |
582 | } | |
583 | switch (fRoundingMode) { | |
584 | case DecimalFormat::kRoundHalfEven: | |
585 | default: | |
586 | // Implement IEEE half-even rounding | |
587 | return maximumDigits > 0 && (fDigits[maximumDigits-1] % 2 != 0); | |
588 | case DecimalFormat::kRoundHalfDown: | |
589 | return FALSE; | |
590 | case DecimalFormat::kRoundHalfUp: | |
b75a7d8f A |
591 | return TRUE; |
592 | } | |
593 | } | |
03115e54 | 594 | return (fDigits[maximumDigits] > '5'); |
b75a7d8f | 595 | } |
b75a7d8f A |
596 | } |
597 | ||
598 | // ------------------------------------- | |
599 | ||
600 | // In the Java implementation, we need a separate set(long) because 64-bit longs | |
601 | // have too much precision to fit into a 64-bit double. In C++, longs can just | |
602 | // be passed to set(double) as long as they are 32 bits in size. We currently | |
603 | // don't implement 64-bit longs in C++, although the code below would work for | |
604 | // that with slight modifications. [LIU] | |
605 | /* | |
606 | void | |
607 | DigitList::set(long source) | |
608 | { | |
609 | // handle the special case of zero using a standard exponent of 0. | |
610 | // mathematically, the exponent can be any value. | |
611 | if (source == 0) | |
612 | { | |
613 | fcount = 0; | |
614 | fDecimalAt = 0; | |
615 | return; | |
616 | } | |
617 | ||
618 | // we don't accept negative numbers, with the exception of long_min. | |
619 | // long_min is treated specially by being represented as long_max+1, | |
620 | // which is actually an impossible signed long value, so there is no | |
621 | // ambiguity. we do this for convenience, so digitlist can easily | |
622 | // represent the digits of a long. | |
623 | bool islongmin = (source == long_min); | |
624 | if (islongmin) | |
625 | { | |
626 | source = -(source + 1); // that is, long_max | |
627 | islongmin = true; | |
628 | } | |
629 | sprintf(fdigits, "%d", source); | |
630 | ||
631 | // now we need to compute the exponent. it's easy in this case; it's | |
632 | // just the same as the count. e.g., 0.123 * 10^3 = 123. | |
633 | fcount = strlen(fdigits); | |
634 | fDecimalAt = fcount; | |
635 | ||
636 | // here's how we represent long_max + 1. note that we always know | |
637 | // that the last digit of long_max will not be 9, because long_max | |
638 | // is of the form (2^n)-1. | |
639 | if (islongmin) | |
640 | ++fdigits[fcount-1]; | |
641 | ||
642 | // finally, we trim off trailing zeros. we don't alter fDecimalAt, | |
643 | // so this has no effect on the represented value. we know the first | |
644 | // digit is non-zero (see code above), so we only have to check down | |
645 | // to fdigits[1]. | |
646 | while (fcount > 1 && fdigits[fcount-1] == kzero) | |
647 | --fcount; | |
648 | } | |
649 | */ | |
650 | ||
651 | /** | |
652 | * Return true if this object represents the value zero. Anything with | |
653 | * no digits, or all zero digits, is zero, regardless of fDecimalAt. | |
654 | */ | |
655 | UBool | |
656 | DigitList::isZero() const | |
657 | { | |
658 | for (int32_t i=0; i<fCount; ++i) | |
659 | if (fDigits[i] != kZero) | |
660 | return FALSE; | |
661 | return TRUE; | |
662 | } | |
663 | ||
b75a7d8f A |
664 | U_NAMESPACE_END |
665 | ||
666 | //eof |