View Javadoc
1   
2   
3   package eu.simuline.util;
4   
5   import java.math.BigInteger;
6   import java.math.BigDecimal;
7   
8   import java.util.Map;
9   import java.util.HashMap;
10  
11  /**
12   * Describes the representation of a real value, 
13   * which may be either a double, resp. a Double-value 
14   * or a {@link BigDecimal} for use in tables. 
15   * At a rudimentary stage, {@link RealRepresentation} wraps the number 
16   * whereas {@link RealRepresentation.Desc} describes 
17   * how to format it, e.g. where to add blanks. 
18   * <p>
19   * Also {@link #asInteger} provides some support for formatting integers. 
20   * These are the two supported levels of precision. 
21   * It is characterized by the {@link #mantissa} and the {@link #exponent}. 
22   * The mantissa in turn 
23   * splits into the {@link #integer} and the {@link #fraction}al part. 
24   * The essential point is that these three parts are properly aligned 
25   * and filled up with <code>0</code>'s and blanks by need. 
26   * <p>
27   * The splitting between integer, fraction and exponent is 
28   * as specified for {@link Double#toString(double)}. 
29   * The difference between the two levels of precision 
30   * is made as transparent as possible. 
31   * Transparence is given up in (at least) the following cases: 
32   * <ul>
33   * <li>
34   * unlike <code>BigDecimal</code>s 
35   * <code>double</code>s (influenced by the standard IEEE 754), 
36   * distinguish between <code>+0</code> and <code>-0</code>. 
37   * <li>
38   * for doubles by specification of the string representation, 
39   * <pre>
40   * "There must be at least one digit to represent the fractional part, 
41   * and beyond that as many, but only as many, 
42   * more digits as are needed to uniquely distinguish the argument value 
43   * from adjacent values of type double. 
44   * That is, suppose that x is the exact mathematical value 
45   * represented by the decimal representation produced by this method 
46   * for a finite nonzero argument d. 
47   * Then d must be the double value nearest to x; 
48   * or if two double values are equally close to x, 
49   * then d must be one of them 
50   * and the least significant bit of the significand of d must be 0. "
51   * </pre>
52   * This does not make sense for <code>BigDecimals</code> 
53   * because there is no nearest <code>BigDecimal</code>: 
54   * The <code>BigDecimal</code>s are "almost" dense in the real numbers. 
55   * Instead we neglect any trailing zeros. 
56   * In later versions, this should be different. 
57   * </ul>
58   *
59   * Also infinite <code>double</code>'s and <code>NaN</code> are not supported. 
60   * This is because they have no splitting into integer, 
61   * fractional part and exponent. 
62   * They do not make sense for <code>BigDecimal</code>s 
63   * and so this would make transparency more difficult. 
64   * Note that denormalization of <code>double</code>'s 
65   * does not affect their string representation 
66   * such that this is completely as forfor<code>BigDecimal</code>s 
67   * for which automatic denormalization does not make sense 
68   * (although can be forced by the user). 
69   *
70   */
71  public class RealRepresentation {
72  
73      /* -------------------------------------------------------------------- *
74       * class constants.                                                     *
75       * -------------------------------------------------------------------- */
76  
77      /**
78       * Describe the action to be taken if a sequence of symbols, 
79       * e.g. digits are longer as needed. 
80       *
81       * @see #alignLeft
82       * @see #alignRight
83       */
84      public static final Cutter ALIGN_CUT_OFF_LEFT = new Cutter() {
85  	    public String cut(String str, int len) {
86  		int strLen = str.length();
87  		return str.substring(strLen - len, strLen);
88  	    }
89  	};
90  
91      /**
92       * Describe the action to be taken if a sequence of symbols, 
93       * e.g. digits are longer as needed. 
94       *
95       * @see #alignLeft
96       * @see #alignRight
97       */
98      public static final Cutter ALIGN_CUT_OFF_RIGHT = new Cutter() {
99  	    public String cut(String str, int len) {
100 		return str.substring(0, len);
101 	    }
102 	};
103 
104     /**
105      * Describe the action to be taken if a sequence of symbols, 
106      * e.g. digits are longer as needed. 
107      *
108      * @see #alignLeft
109      * @see #alignRight
110      * @see #trimExponent
111      */
112     public static final Cutter ALIGN_EXCEPTION = new Cutter() {
113 	    public String cut(String str, int len) {
114 		throw new IllegalArgumentException
115 		    ("String \"" + str + "\" longer than expected (" + 
116 		     len + "). ");
117 
118 	    }
119 	};
120 
121     /**
122      * Describe the action to be taken if a sequence of symbols, 
123      * e.g. digits are longer as desired. 
124      *
125      * @see #alignLeft
126      * @see #alignRight
127      * @see #trimExponent
128      */
129     public static final Cutter ALIGN_LEAVE_UNCHANGED = new Cutter() {
130 	    public String cut(String str, int len) {
131 		return str;
132 	    }
133 	};
134 
135     /**
136      * The keys are Characters (intended for either " " or "0") 
137      * and the associated values are strings 
138      * consisting of a number of characters given by the key. 
139      *
140      * @see #fill
141      */
142     private static final Map<Character, String> FILL_STRINGS = 
143 	new HashMap<Character, String>();
144 
145     /**
146      * A string containing the character signifying an exponent. 
147      * This is <code>e</code> but could also be <code>E</code>.
148      */
149     public  static final String EXP_CHAR = "e";
150 
151     /**
152      * Substitutes the place for the point 
153      * in case the real number represented has no fractional part. 
154      * This is either " " or "". 
155      * The default value is " ". 
156      *
157      * @see #compensatePoint
158      */
159     private       static String   noPointS = " ";
160 
161     /**
162      * A string constant containing the decimal point. 
163      */
164     private static final String    POINT_S = ".";
165 
166     /**
167      * A character constant containing <code>+</code>. 
168      */
169     private static final String SIGN_PLUS  = "+";
170 
171     /**
172      * A character constant containing <code>+</code>. 
173      */
174     private static final String SIGN_MINUS = "-";
175 
176     /**
177      * Sets {@link #noPointS} according to the parameter: 
178      * <code>true</code> means that {@link #noPointS} is attached with " "; 
179      * otherwise it is "". 
180      *
181      * @param compensate 
182      *    a <code>boolean</code> deciding 
183      *    whether to compensate a decimal point 
184      *    in case the real number represented has no fractional part. 
185      */
186     public static void compensatePoint(boolean compensate) {
187 	noPointS = compensate ? " " : "";
188     }
189 
190     /* -------------------------------------------------------------------- *
191      * inner classes.                                                       *
192      * -------------------------------------------------------------------- */
193 
194     /**
195      * Describes the representation of a {@link BigDecimal}-value. 
196      * It is characterized 
197      * by the {@link #mantissa} and the {@link #exponent}. 
198      * The mantissa in turn 
199      * splits into the {@link #integer} and the {@link #fraction}al part. 
200      *
201      * @author <a href="mailto:e.reissner@rose.de">Ernst Reissner</a>
202      * @version 1.0
203      */
204     private static final class BigDecimalRep extends RealRepresentation {
205 
206 	/**
207 	 * The number of digits right of the point 
208 	 * such that the representation is without exponent. 
209 	 * This evaluates to <code>-3</code> as specified for double's 
210 	 * in {@link Double#toString(double)} and is used by 
211 	 * {@link #BigDecimalRep(BigDecimal)}. 
212 	 */
213 	private static final int MAX_FRAC_DIGITS_NO_EXP = -3;
214 
215 	/**
216 	 * The number of digits left of the point 
217 	 * such that the representation is without exponent. 
218 	 * This evaluates to <code>7</code> as specified for double's 
219 	 * in {@link Double#toString(double)} and is used by 
220 	 * {@link #BigDecimalRep(BigDecimal)}. 
221 	 */
222 	private static final int MAX_INT_DIGITS_NO_EXP = 7;
223 
224 	/* ---------------------------------------------------------------- *
225 	 * constructors.                                                    *
226 	 * ---------------------------------------------------------------- */
227 
228 	/**
229 	 * Constructs a newly allocated <code>BigDecimalRep</code> 
230 	 * that represents given <code>BigDecimal</code> argument. 
231 	 *
232 	 * @param dec 
233 	 *    the value to be represented 
234 	 *    by this <code>BigDecimalRep</code>. 
235 	 */
236 	@SuppressWarnings({"checkstyle:nowhitespacebefore",
237 		"checkstyle:nowhitespaceafter"})
238 	BigDecimalRep(BigDecimal dec) {
239 	    switch (dec.signum()) {
240 	    case -1:
241 		this.sign = SIGN_MINUS;
242 		dec = dec.abs();
243 		break;
244 	    case  0:
245 		//assert exp == 0;
246 		this.sign = SIGN_PLUS;
247 		this.integer = "0";
248 		//this.mantissa ="0.0";
249 		this.fraction = "0";
250 		this.exponent = "";
251 		return;
252 	    case  1:
253 		this.sign = SIGN_PLUS;
254 		break;
255 	    default:
256 		throw new IllegalStateException
257 		    ("Found unexpected sign " + dec.signum() + ". ");
258 	    }
259 	    // Here, d is not zero, mantissa is not "0" and has no sign. 
260 
261 	    int exp = -dec.scale();
262 	    String mantissa = dec.unscaledValue().toString();
263 
264 	    int lenMant = mantissa.length();
265 	    if (new BigDecimal("1.0e" + MAX_FRAC_DIGITS_NO_EXP).compareTo(dec)
266 		<= 0 && 
267 		new BigDecimal("1.0e" +  MAX_INT_DIGITS_NO_EXP).compareTo(dec)
268 		> 0) {
269 		// the representation is xxx.yyy without exponent. 
270 		this.exponent = "";
271 		if (BigDecimal.valueOf(1).compareTo(dec) > 0) {
272 		    // Here, 0 < d < 1. 
273 		    mantissa = alignRight(mantissa,
274 					  1 - exp,
275 					  '0',
276 					  ALIGN_EXCEPTION);
277 		}
278 		// the representation xxx.yyy with nontrivial integer part. 
279 		this.integer  = mantissa
280 		    . substring(0            , lenMant + exp);
281 		this.fraction = mantissa
282 		    . substring(lenMant + exp, lenMant      );
283 	    } else {
284 		// representation a.yyyezzz with exponent 
285 		// where a is a digit != 0. 
286 		this.exponent = Integer
287 		    .toString(exp + lenMant - 1);
288 		this.integer  = mantissa.substring(0, 1);
289 		this.fraction = mantissa.substring(1, lenMant);
290 	    }
291 
292 	    // remove trailing zeros. 
293 	    this.fraction = this.fraction.replaceFirst("0*$", "");
294 	    // add a zero if nothing else is left. 
295 	    if (this.fraction.length() == 0) {
296 		this.fraction = "0";
297 	    }
298 	    //this.mantissa = 
299 	    //	this.integer + POINT_S + this.fraction;
300 	}
301 
302 	/**
303 	 * Constructs a newly allocated 
304 	 * <code>BigDecimalRep</code> object 
305 	 * that represents the floating-point value of type double 
306 	 * represented by the string. 
307 	 * The string is converted to a double value 
308 	 * as if by the method {@link Double#valueOf}. 
309 	 *
310 	 * @param dStr 
311 	 *    a string to be converted 
312 	 *    to a <code>BigDecimalRep</code>. 
313 	 * @see Double#Double(String)
314 	 */
315 	BigDecimalRep(String dStr) {
316 	    this(new BigDecimal(dStr));
317 	}
318     } // class BigDecimalRep
319 
320     /**
321      * Describes the representation of a double, resp. a Double-value. 
322      * It is characterized 
323      * by the {@link #mantissa} and the {@link #exponent}. 
324      * The mantissa in turn 
325      * splits into the {@link #integer} and the {@link #fraction}al part. 
326      *
327      * @author <a href="mailto:e.reissner@rose.de">Ernst Reissner</a>
328      * @version 1.0
329      */
330     private static final class DoubleRep extends RealRepresentation {
331 
332 	/* ---------------------------------------------------------------- *
333 	 * constructors.                                                    *
334 	 * ---------------------------------------------------------------- */
335 
336 	/**
337 	 * Constructs a newly allocated 
338 	 * <code>DoubleRep</code> object 
339 	 * that represents the primitive <code>double</code> argument. 
340 	 *
341 	 * @param dbl 
342 	 *    the value to be represented 
343 	 *    by this <code>DoubleRep</code>. 
344 	 * @see Double#Double(double)
345 	 * @throws NumberFormatException
346 	 *    if <code>d</code> is either infinite or not a number. 
347 	 */
348 	DoubleRep(double dbl) {
349 
350 	    // Exclude that d is NaN or infinite 
351 	    if (Double.isNaN(dbl) || Double.isInfinite(dbl)) {
352 		// Replace dbl by |dbl| 
353 		// because of bug in constructor BigDecimal(double). 
354 		throw new NumberFormatException
355 		    ("For input string: \"" + Math.abs(dbl) + "\"");
356 	    }
357 	    // Here d is neither NaN nor infinite. 
358 
359 	    String str = Double.toString(dbl);
360 	    String mantissa;
361 	    int index;
362 	    index = str.indexOf('E');
363 	    if (index == -1) {
364 		index = str.indexOf('e');
365 	    }
366 	    // Here, either index == -1 or index is the index of the exp. 
367 
368 	    if (index == -1) {
369 		// Here, no exponent is given. 
370 		this.exponent = "";
371 		mantissa = str;
372 	    } else {
373 		// Here, an exponent is given. 
374 		this.exponent = str.substring(index + 1, str.length());
375 		mantissa = str.substring(0, index);
376 		initSignExp();
377 	    }
378 	    // Here, mantissa and exponent are separated 
379 	    // and also str is not empty. 
380 
381 	    // extract sign (also think of the distinction -0.0 and +0.0). 
382 	    Number2SignUnsigned sus = new Number2SignUnsigned(mantissa);
383 	    this.sign = sus.getSign();
384 	    mantissa = sus.getUnSigned();
385 	    // Here, str is the unsigned mantissa. 
386 
387 	    index = mantissa.indexOf(POINT_S);
388 	    if (index == -1) {
389 		// no decimal point: mantissa is an integer. 
390 		// according to the docs of Double.toString(double) 
391 		// this does not occur, but...
392 		throw new IllegalStateException
393 		    ("Unlike specified for Double.toString(double) " + 
394 		     "found no decimal point in \"" + mantissa + "\". ");
395 	    }
396 	    this.integer  = mantissa.substring(0, index);
397 	    this.fraction = mantissa.substring(index + 1,
398 					       mantissa.length());
399 	    // Here, mantissa is separated into integer and fraction. 
400 	}
401 
402 	/**
403 	 * Constructs a newly allocated 
404 	 * <code>DoubleRep</code> object 
405 	 * that represents the floating-point value of type double 
406 	 * represented by the string. 
407 	 * The string is converted to a double value 
408 	 * as if by the method {@link Double#valueOf}. 
409 	 *
410 	 * @param dStr 
411 	 *    a string to be converted 
412 	 *    to a <code>DoubleRep</code>. 
413 	 * @see Double#Double(String)
414 	 * @throws IllegalArgumentException
415 	 *    if <code>d</code> is either infinite or not a number. 
416 	 * @throws NumberFormatException
417 	 *    if <code>d</code> has not the appropriate number format. 
418 	 */
419 	DoubleRep(String dStr) {
420 	    this(Double.parseDouble(dStr));
421 	}
422 
423 	/**
424 	 * Creates a new <code>DoubleRep</code>. 
425 	 * An analog to {@link DoubleRep(double)}. 
426 	 *
427 	 * @param dbl 
428 	 *    a <code>Double</code> object. 
429 	 * @throws IllegalArgumentException
430 	 *    if <code>d</code> is either infinite or not a number. 
431 	 */
432 	DoubleRep(Double dbl) {
433 	    this(dbl.doubleValue());
434 	}
435 
436 	/* ---------------------------------------------------------------- *
437 	 * general methods.                                                 *
438 	 * ---------------------------------------------------------------- */
439 
440     } // class DoubleRep 
441 
442     /**
443      * A <code>Cutter</code> is used to shorten numbers. 
444      * This can either be done by cutting, by rounding or somenthing else. 
445      */
446     public interface Cutter {
447 	/**
448 	 * Returns a substring of <code>str</code> 
449 	 * with length <code>len</code> or throws an exception. 
450 	 *
451 	 * @param str 
452 	 *    a <code>String</code> with <code>str.length() &gt;= len</code>. 
453 	 * @param len 
454 	 *    the desired length of the resulting string. 
455 	 * @return 
456 	 *    a substring of <code>str</code> with length <code>len</code>. 
457 	 * @throws RuntimeException
458 	 *    by need if the cut is not allowed. 
459 	 */
460 	String cut(String str, int len);
461     } // interface Cutter 
462 
463     /**
464      * Container for number splitted into sign and unsigned. 
465      */
466     private static class Number2SignUnsigned {
467 
468 	/**
469 	 * The sign which is either {@link #SIGN_PLUS} or {@link #SIGN_MINUS}. 
470 	 */
471 	private final String sign;
472 
473 	/**
474 	 * The unsigned part of a number. 
475 	 */
476 	private final String unSigned;
477 
478 	/**
479 	 * Creates a new <code>Number2SignUnsigned</code> instance 
480 	 * wrapping a string representation of a number.
481 	 *
482 	 * @param signed 
483 	 *    a <code>String</code> representation of a number. 
484 	 *    There may be either an explicit sign 
485 	 *    or the first symbol is a digit. 
486 	 * @throws NumberFormatException
487 	 *    if the first symbol is neither a sign nor a digit. 
488 	 */
489 	Number2SignUnsigned(String signed) {
490 	    // extract sign (also think of the distinction -0.0 and +0.0). 
491 	    switch (signed.charAt(0)) {
492 	    case '+':
493 		// explicit + sign 
494 		this.sign = SIGN_PLUS;
495 		this.unSigned = signed.substring(1, signed.length());
496 		break;
497 	    case '-':
498 		// explicit - sign 
499 		this.sign = SIGN_MINUS;
500 		this.unSigned = signed.substring(1, signed.length());
501 		break;
502 	    default:
503 		// implicit + sign 
504 		// Here, one should have some digit at the 0th place. 
505 		if (!signed.substring(0, 1).matches("\\d")) {
506 		    throw new NumberFormatException
507 			("Expected unsigned number found " + signed + ". ");
508 		}
509 		this.sign = SIGN_PLUS;
510 		this.unSigned = signed;
511 	    }
512 	}
513 
514 	String getSign() {
515 	    return this.sign;
516 	}
517 
518 	String getUnSigned() {
519 	    return this.unSigned;
520 	}
521 
522     } // class Number2SignUnsigned 
523 
524 
525     /**
526      * Describes the way 
527      * the real number represented by {@link RealRepresentation} 
528      * is displayed as a string. 
529      */
530     public static class Desc {
531 
532 	/* ---------------------------------------------------------------- *
533 	 * fields.                                                          *
534 	 * ---------------------------------------------------------------- */
535 
536 	/**
537 	 * Signifies whether an attempt 
538 	 * to cut off parts of the integer will result in an exception; 
539 	 * otherwise it is just ignored. 
540 	 */
541 	@SuppressWarnings("PMD.FinalFieldCouldBeStatic")
542 	@edu.umd.cs.findbugs.annotations.SuppressWarnings
543 	(value = "SS_SHOULD_BE_STATIC", 
544 	 justification = "not now")
545 	 private final boolean strictInteger = false;
546 
547 	/**
548 	 * Signifies whether an attempt 
549 	 * to cut off parts of the exponent will result in an exception; 
550 	 * otherwise it is just ignored. 
551 	 */
552 	@SuppressWarnings("PMD.FinalFieldCouldBeStatic")
553 	@edu.umd.cs.findbugs.annotations.SuppressWarnings
554 	(value = "SS_SHOULD_BE_STATIC", 
555 	 justification = "not now")
556 	private final boolean strictExponent = false;
557 
558 	private  final Cutter fractionCutter = ALIGN_CUT_OFF_RIGHT;
559 
560 	/**
561 	 * The maximal length of the integer part of a number
562 	 * displayed in a specific column of the table.
563 	 */
564 	private final int lenI;
565 
566 	/**
567 	 * The maximal length of the mantissa of a number
568 	 * displayed in a specific column of the table.
569 	 * @see #lenI
570 	 */
571 	private final int lenM;
572 
573 	/**
574 	 * The maximal length of the exponent part of a number
575 	 * displayed in a specific column of the table.
576 	 * @see #lenI
577 	 */
578 	private final int lenE;
579 
580 
581 	/* ---------------------------------------------------------------- *
582 	 * constructors.                                                    *
583 	 * ---------------------------------------------------------------- */
584 
585 	// **** under construction. 
586 	public Desc(int lenI, int lenM, int lenE) {
587 	    this.lenI = lenI;
588 	    this.lenM = lenM;
589 	    this.lenE = lenE;
590 	}
591     } // class Desc 
592 
593 
594     /* -------------------------------------------------------------------- *
595      * fields.                                                              *
596      * -------------------------------------------------------------------- */
597 
598     /**
599      * The sign of the double value represented. 
600      * This may be either {@link #SIGN_PLUS +} or {@link #SIGN_MINUS -}. 
601      * Note that the standard IEEE 754 distinguishes <code>-0</code> 
602      * from <code>+0</code> and so do we in the subclass 
603      * {@link RealRepresentation.DoubleRep}. 
604      */
605     @SuppressWarnings("checkstyle:visibilitymodifier")
606     protected String sign;
607 
608     /*
609      * The mantissa of the double value represented. 
610      */
611     //protected String mantissa;
612 
613     /**
614      * The integer part of the mantissa of the double value represented. 
615      */
616     @SuppressWarnings("checkstyle:visibilitymodifier")
617     protected String integer;
618 
619     /**
620      * The fractional part of the mantissa of the double value represented. 
621      * This may never be empty but it may be <code>0</code>. 
622      */
623     @SuppressWarnings("checkstyle:visibilitymodifier")
624     protected String fraction;
625 
626 
627     /**
628      * The exponent of the double value represented. 
629      */
630     @SuppressWarnings("checkstyle:visibilitymodifier")
631     protected String exponent;
632 
633     private String signOfExp; // NOPMD 
634 
635     private String unsignedExp; // NOPMD 
636 
637     /* -------------------------------------------------------------------- *
638      * create methods: out of Strings, doubles, Doubles and BigDecimals.    *
639      * -------------------------------------------------------------------- */
640 
641     @edu.umd.cs.findbugs.annotations.SuppressWarnings
642 	(value = "URF_UNREAD_FIELD", 
643 	 justification = "to be used in later versions ")
644     protected final void initSignExp() {
645 	Number2SignUnsigned sus = new Number2SignUnsigned(this.exponent);
646 	this.signOfExp = sus.getSign();
647 	this.unsignedExp = sus.getUnSigned();
648     }
649 
650     /**
651      * Converts the given string representation of a real number 
652      * to a <code>RealRepresentation</code> with the given precision. 
653      *
654      * @param val 
655      *    a <code>String</code> representation of a real number. 
656      * @param precision 
657      *    a <code>boolean</code> which offers choice between 
658      *    full precision (<code>true</code>) and 
659      *    double precision (<code>false</code>). 
660      * @return 
661      *    a <code>RealRepresentation</code> of the real value 
662      *    given by the string representation <code>val</code> 
663      *    with the precision determined by <code>precision</code>. 
664      * @throws NumberFormatException
665      *   if <code>val</code> is not the string representation of a double 
666      *   or if it is <code>NaN</code> or represents an infinite value. 
667      */
668     public static RealRepresentation create(String val, boolean precision) {
669 	return precision ? new BigDecimalRep(val) : new     DoubleRep(val);
670     }
671 
672     /**
673      * Converts the given high precision representation of a real number 
674      * to a <code>RealRepresentation</code> 
675      * preserving full precision if so specified. 
676      *
677      * @param val 
678      *    a <code>Number</code> value 
679      *    which is either a {@link BigDecimal} or a <code>Double</code>. 
680      * @param precision 
681      *    specifies whether to preserve full precision. 
682      *    If set to <code>false</code> 
683      *    only <code>double</code> precision is used. 
684      * @return 
685      *    a <code>RealRepresentation</code> of the real value 
686      *    given by <code>val</code> 
687      *    preserving full precision is specified so. 
688      * @throws ClassCastException 
689      *    if <code>val</code> is neither a {@link BigDecimal} 
690      *    nor a <code>Double</code>. 
691      */
692     public static RealRepresentation create(Number val,
693 					    boolean precision) {
694 	if (precision) {
695 	    return (val instanceof BigDecimal)
696 		? new BigDecimalRep( (BigDecimal) val               )
697 		: new     DoubleRep(((Double    ) val).doubleValue());
698 	} else {
699 	    return new DoubleRep(val.doubleValue());
700 	}
701     }
702 
703     /**
704      * Converts the given <code>double</code> number 
705      * to a <code>RealRepresentation</code> with the given precision. 
706      *
707      * @param val 
708      *    a <code>double</code> value. 
709      * @param precision 
710      *    a <code>boolean</code> which offers choice between 
711      *    full precision (<code>true</code> which is obsolete****) and 
712      *    double precision (<code>false</code>). 
713      * @return 
714      *    a <code>RealRepresentation</code> of the given <code>double</code> 
715      *    with the precision determined by <code>precision</code>. 
716      * @throws NumberFormatException
717      *   if <code>val</code> is either <code>NaN</code> or infinite. 
718      */
719     public static RealRepresentation create(double val,
720 					    boolean precision) {
721 	return create(Double.valueOf(val), precision);
722     }
723 
724     /**
725      * Converts the given number 
726      * to a <code>RealRepresentation</code> with the natural precision. 
727      *
728      * @param val 
729      *    a <code>Number</code> value 
730      *    which is either a {@link BigDecimal} or a <code>Double</code>. 
731      * @return 
732      *    a <code>RealRepresentation</code> of the given number 
733      *    with the natural precision: 
734      *    <code>create((BigDecimal)val, true)</code> or 
735      *    <code>create((Double    )val, true)</code>. 
736      * @throws ClassCastException 
737      *    if <code>val</code> is neither a {@link BigDecimal} 
738      *    nor a <code>Double</code>. 
739      */
740     public static RealRepresentation create(Number val) {
741 	return val instanceof BigDecimal 
742 	    ? create((BigDecimal) val, true) 
743 	    : create((Double    ) val, false);
744     }
745 
746     /* -------------------------------------------------------------------- *
747      * methods for aligning strings.                                        *
748      * -------------------------------------------------------------------- */
749 
750     /**
751      * Returns a <code>String</code> 
752      * consisting of <code>len</code> copies of the character <code>c</code>. 
753      *
754      * @param chr0 
755      *    a <code>char</code>. 
756      * @param len 
757      *    the number of repetitions of <code>c</code> needed. 
758      *    This should be a non-negative integer. 
759      * @return 
760      *    a <code>String</code> consisting of <code>len</code> characters 
761      *    <code>c</code>. 
762      */
763     public static String fill(char chr0, int len) {
764 	Character chr = Character.valueOf(chr0);
765 	String cutString = FILL_STRINGS.get(chr);
766 	// by contract, cutString is either null or 
767 	// its length is 2^n for some natural number n. 
768 	boolean copyBack = false;
769 	if (cutString == null) {
770 	    cutString = chr.toString(); //Character.toString(c);
771 	    copyBack  = true;
772 	}
773 	
774 	// Here, cutString != null && cutString.length() > 0 
775 
776 	if (cutString.length() < len) {
777 	    copyBack  = true;
778 	    StringBuffer cutBuf = new StringBuffer(cutString);
779 	    while (cutBuf.length() < len) {
780 		cutBuf.append(cutBuf);
781 	    }
782 	    cutString = cutBuf.toString();
783 	}
784 
785 	// Here, cutString != null && cutString.length() >= len 
786 	if (copyBack) {
787 	    FILL_STRINGS.put(chr, cutString);
788 	}
789 	// Here, (String)FILL_STRINGS.get(chr).equals(cutString) again.  
790 
791 	return cutString.substring(0, len);
792     }
793 
794     /**
795      * Returns a <code>String</code> which is 
796      * by attaching the minimal number of <code>filler</code>s 
797      * to the right hand side of <code>str</code> 
798      * such that the length of the result is at least <code>int</code>. 
799      * For <code>strict == true</code> even equality is assured. 
800      *
801      * @param str 
802      *    the <code>String</code> to be aligned. 
803      * @param len 
804      *    an <code>int</code> value which determines 
805      *    the length of the result string: 
806      * @param filler 
807      *    a <code>char</code> value. 
808      * @param  cutter
809      *    takes effect if <code>str.length &gt; len</code>: 
810      *    <ul>
811      *    <li>
812      *    for {@link #ALIGN_CUT_OFF_RIGHT} superfluous digits are cut off, 
813      *    <li> {
814      *    for {@link #ALIGN_EXCEPTION} superfluous digits cause an exception, 
815      *    <li>
816      *    for {@link #ALIGN_LEAVE_UNCHANGED} 
817      *    superfluous digits are left unchanged, 
818      *    </ul>
819      * @return 
820      *    <ul>
821      *    <li> for <code>str.length()&le;len</code> 
822      *    copies of  <code>filler</code>s 
823      *    are attached to the right hand side of <code>str</code> 
824      *    such that the length of the result is least <code>int</code>. 
825      *    <li> for <code>str.length()&gt;len</code> 
826      *    <ul>
827      *    <li> 
828      *    <code>str</code> is returned as is 
829      *    provided <code>cutter == {@link #ALIGN_LEAVE_UNCHANGED}</code> 
830      *    <li> 
831      *    For <code>cutter == {@link #ALIGN_EXCEPTION}</code> 
832      *    there is no return value: 
833      *    an exception is thrown and finally 
834      *    <li> 
835      *    for <code>cutter == {@link #ALIGN_CUT_OFF_RIGHT}</code> 
836      *    the overhead is silently cut off. 
837      *    </ul>
838      *    </ul>
839      * @throws IllegalArgumentException 
840      *    for <code>cutter == {@link #ALIGN_EXCEPTION}</code> 
841      *    if <code>str.length()</code> exceeds <code>len</code>. 
842      */
843     public static String alignLeft(String str, 
844 				   int len,
845 				   char filler,
846 				   Cutter cutter) {
847 	int strLen = str.length();
848 	return strLen > len 
849 	    ? cutter.cut(str, len) 
850 	    : str + fill(filler, len - strLen);
851     }
852 
853     /**
854      * Returns a <code>String</code> which is 
855      * by attaching the minimal number of <code>filler</code>s 
856      * to the left hand side of <code>str</code> 
857      * such that the length of the result is at least <code>int</code>. 
858      * For <code>strict == true</code> even equality is assured. 
859      *
860      * @param str 
861      *    the <code>String</code> to be aligned. 
862      * @param len 
863      *    an <code>int</code> value which determines 
864      *    the length of the result string: 
865      * @param filler 
866      *    a <code>char</code> value. 
867      * @param  cutter
868      *    takes effect if <code>str.length &gt; len</code>:  { {
869      *    <ul>
870      *    <li>
871      *    for {@link #ALIGN_CUT_OFF_LEFT} superfluous digits are cut off, 
872      *    <li>
873      *    for {@link #ALIGN_EXCEPTION} superfluous digits cause an exception, 
874      *    <li>
875      *    for {@link #ALIGN_LEAVE_UNCHANGED} 
876      *    superfluous digits are left unchanged, 
877      *    </ul>
878      * @return 
879      *    <ul>
880      *    <li> for <code>str.length()&le;len</code> 
881      *    copies of  <code>filler</code>s 
882      *    are attached to the right hand side of <code>str</code> 
883      *    such that the length of the result is least <code>int</code>. 
884      *    <li> for <code>str.length()&gt;len</code> 
885      *    <ul>
886      *    <li> 
887      *    <code>str</code> is returned as is 
888      *    provided <code>cutter == {@link #ALIGN_LEAVE_UNCHANGED}</code> 
889      *    <li> 
890      *    For <code>cutter == {@link #ALIGN_EXCEPTION}</code> 
891      *    there is no return value: 
892      *    an exception is thrown and finally 
893      *    <li> 
894      *    for <code>cutter == {@link #ALIGN_CUT_OFF_LEFT}</code> 
895      *    the overhead is silently cut off. 
896      *    </ul>
897      *    </ul>
898      * @throws IllegalArgumentException 
899      *    for <code>cutter == {@link #ALIGN_EXCEPTION}</code> 
900      *    if <code>str.length()</code> exceeds <code>len</code>. 
901      */
902     public static String alignRight(String str,
903 				    int len,
904 				    char filler,
905 				    Cutter cutter) {
906 	int strLen = str.length();
907 	return  strLen > len 
908 	    ? cutter.cut(str, len) 
909 	    : fill(filler, len - strLen) + str;
910     }
911 
912     /* -------------------------------------------------------------------- *
913      * trim and cut methods.                                                *
914      * -------------------------------------------------------------------- */
915 
916     /*
917     private void updateMantissa() {
918 	this.mantissa = 
919 	    this.integer +
920 	    (hasFraction() ? POINT_S : noPointS) + 
921 	    this.fraction;
922     }
923     */
924 
925     // **** for align methods: message of exception 
926     // Cannot trim integer " + this.integer +  " to " + numDigits + " digits. "
927     // better than current one. 
928     /**
929      * Trims the integer part 
930      * to length <code>numDigits</code> if possible. 
931      * If this leads to a prolongation of the integer part, 
932      * it is filled up with characters <code>blankOrNull</code> 
933      * from the left hand side. 
934      * If the integer part is already longer than specified, 
935      * the action taken relies on the parameter <code>strict</code>. 
936      * Caution: ***** this does not work very well 
937      * for <code>numDigits = 0</code>. 
938      * Caution: **** not ok with signs. 
939      * Caution: **** what to do if ".4" is needed? 
940      *
941      * @param numDigits 
942      *    a non-negative <code>int</code> value signifying the length 
943      *    of the integer part. 
944      * @param blankOrNull 
945      *    a <code>char</code> with which the integer part is filled up 
946      *    by need from the left hand side 
947      *    to reach length <code>numDigits</code>. 
948      *    Useful settings are probably blank and <code>'0'</code> only. 
949      * @param strict 
950      *    a <code>boolean</code> signifying whether an attempt 
951      *    to cut off parts of the integer will result in an exception; 
952      *    otherwise it is just ignored. 
953      * @return 
954      *    the new integer part as a <code>String</code>. 
955      * @throws IllegalArgumentException 
956      *    for <code>strict( == true)</code> 
957      *    if the length of the integer part exceeds <code>numDigits</code>. 
958      */
959     public final String trimInteger(int numDigits,
960 			      char blankOrNull,
961 			      boolean strict) {
962 	Cutter cutter = strict ? ALIGN_EXCEPTION : ALIGN_LEAVE_UNCHANGED;
963 	this.integer = alignRight(this.integer,
964 				  numDigits,
965 				  blankOrNull,
966 				  cutter);
967 	//updateMantissa();
968 	return this.integer;
969     }
970 
971     /**
972      * Trims the exponent part 
973      * to length <code>numDigits</code> if possible. 
974      * If this leads to a prolongation of the exponent part, 
975      * it is filled up with characters <code>blankOrNull</code> 
976      * from the left hand side. 
977      * If the exponent part is already longer than specified, 
978      * the action taken relies on the parameter <code>strict</code>. 
979      * Caution: ***** this does not work very well 
980      * for <code>numDigits = 0</code>. 
981      * Caution: **** not ok with signs. 
982      * Caution: **** not ok if there are no exponents at all. 
983      *
984      * @param numDigits 
985      *    a non-negative <code>int</code> value signifying the length 
986      *    of the exponent part. 
987      * @param blankOrNull 
988      *    a <code>char</code> with which the exponent part is filled up 
989      *    by need from the left hand side 
990      *    to reach length <code>numDigits</code>. 
991      *    Useful settings are probably blank and <code>'0'</code> only. 
992      * @param strict 
993      *    a <code>boolean</code> signifying whether an attempt 
994      *    to cut off parts of the exponent will result in an exception; 
995      *    otherwise it is just ignored. 
996      * @return 
997      *    the new exponent as a <code>String</code>. 
998      * @throws IllegalArgumentException 
999      *    for <code>strict( == true)</code> 
1000      *    if the length of the exponent part exceeds <code>numDigits</code>. 
1001      */
1002     public final String trimExponent(int numDigits,
1003 			       char blankOrNull,
1004 			       boolean strict) {
1005 	Cutter cutter = strict ? ALIGN_EXCEPTION : ALIGN_LEAVE_UNCHANGED;
1006 	this.exponent = alignRight(this.exponent,
1007 				   numDigits,
1008 				   blankOrNull,
1009 				   cutter);
1010 	return this.exponent;
1011     }
1012 
1013     /**
1014      * Trims the fractional part 
1015      * to length <code>numDigits</code> if possible. 
1016      * If this leads to a prolongation of the fractional part, 
1017      * it is filled up with characters <code>blankOrNull</code>. 
1018      * If the fractional part is already longer than specified, 
1019      * the action taken relies on the code <code>cutter</code>. 
1020      * Caution: ***** this does not work very well 
1021      * for <code>numDigits = 0</code>. 
1022      * Caution: **** this method simply cuts off digits 
1023      * without rounding. 
1024      *
1025      * @param numDigits 
1026      *    a non-negative <code>int</code> value signifying the length 
1027      *    of the fractional part. 
1028      * @param blankOrNull 
1029      *    a <code>char</code> with which the fractional part is filled up 
1030      *    by need to reach length <code>numDigits</code>. 
1031      *    Useful settings are probably <code>'0'</code> and blank only. 
1032      * @param cutter 
1033      *    an <code>int</code> code which is relevant only, 
1034      *    if the current fractional part is longer 
1035      *    than specified by <code>numDigits</code>. 
1036      * @return 
1037      *    the new trimmed fractional part as a <code>String</code>. 
1038      * @throws IllegalArgumentException 
1039      *    for <code>cutter == {@link #ALIGN_EXCEPTION}</code> 
1040      *    if the length of the fractional part 
1041      *    exceeds <code>numDigits</code>. 
1042      */
1043     public final String trimFraction(int numDigits,
1044 			       char blankOrNull,
1045 			       Cutter cutter) {
1046 	this.fraction = 
1047 	    alignLeft(this.fraction, numDigits, blankOrNull, cutter);
1048 	//updateMantissa();
1049 	return this.fraction;
1050     }
1051 
1052     /* -------------------------------------------------------------------- *
1053      * representation methods.                                              *
1054      * -------------------------------------------------------------------- */
1055 
1056     /**
1057      * Converts this representation such that 
1058      * there is neither a {@link #fraction} nor an {@link #exponent}. 
1059      * Of course in general thereby the current format is lost. 
1060      *
1061      * @throws NumberFormatException 
1062      *    if this representation cannot be written as an integer. 
1063      */
1064     public final void asInteger() {
1065 	String trimmedExponent = this.exponent.trim();
1066 	BigInteger expVal = "".equals(trimmedExponent) 
1067 	    ? BigInteger.ZERO 
1068 	    : new BigInteger(trimmedExponent);
1069 	// remove trailing 0's and blanks. 
1070 	String trimmedFraction = this.fraction.replaceAll("0* *$", "");
1071 	expVal = expVal.subtract
1072 	    (new BigInteger(Integer.toString(trimmedFraction.length())));
1073 	this.integer += trimmedFraction;
1074 	// Here the representation this.integer.0EexpVal is without fraction. 
1075 
1076 	this.integer = this.integer.replaceAll("^[0 ]*", "");
1077 	if (this.integer.equals("")) { // also possible with "" but to dangerous
1078 	    this.integer = "0";
1079 	}
1080 	// Here, this.integer has no leading 0's or blanks. 
1081 	
1082 	switch (expVal.signum()) {
1083 	case -1:
1084 	    throw new NumberFormatException
1085 		("Could not represent " + this + " as an integer. ");
1086 	case  0:
1087 	    // nothing to do: representation is already without exponent. 
1088 	    break;
1089 	case  1:
1090 	    this.integer += fill('0', expVal.intValue());
1091 	    break;
1092 	default:
1093 	    throw new IllegalStateException
1094 		("Found signum " + expVal.signum()
1095 		 + " which may be only -1, 0 or 1. ");
1096 	}
1097 
1098 	this.fraction = "";
1099 	this.exponent = "";
1100     }
1101 
1102     /* -------------------------------------------------------------------- *
1103      * get methods.                                                         *
1104      * -------------------------------------------------------------------- */
1105 
1106     public final boolean hasBlankFraction() {
1107 	return !this.fraction.matches("^ *$");
1108     }
1109 
1110     public final boolean hasFraction() {
1111 	return !this.fraction.matches("^0* *$");
1112     }
1113 
1114     public final boolean hasInteger() {
1115 	return !this.integer.matches("^ *0*$");
1116     }
1117 
1118     public final boolean hasExponent() {
1119 	return !this.exponent.matches("^ *$");
1120     }
1121 
1122     public final String sign() {
1123 	return this.sign;
1124     }
1125 
1126     public final String exponent() {
1127 	return this.exponent;
1128     }
1129 
1130     public final String mantissa() {
1131 	return this.integer +
1132 	    (hasBlankFraction() ? POINT_S : noPointS) + 
1133 	    this.fraction;
1134  
1135 	//return this.mantissa;
1136     }
1137 
1138     public final String integer() {
1139 	return this.integer;
1140     }
1141 
1142     public final String fraction() {
1143 	return this.fraction;
1144     }
1145 
1146     /* -------------------------------------------------------------------- *
1147      * inverse create methods:                                              *
1148      * retrieve Strings, doubles, Doubles and BigDecimals.                  *
1149      * -------------------------------------------------------------------- */
1150 
1151     /**
1152      * Returns a <code>Double</code> represented.
1153      *
1154      * @return 
1155      *    a <code>Double</code> <code>d</code> satisfying 
1156      *    {@link #create(Number, boolean) 
1157      *            create(d, false).this2Double().compareTo(d) == 0}. 
1158      */
1159     public final Double this2Double() {
1160 	return Double.valueOf(this.sign + mantissa() + getExpWithE());
1161     }
1162 
1163     /**
1164      * Returns a <code>double</code> represented.
1165      *
1166      * @return 
1167      *    a <code>double</code> <code>d</code> satisfying 
1168      *    {@link #create(double, boolean) create(d, false).this2double() == d}. 
1169      */
1170     public final double this2double() {
1171 	return this2Double().doubleValue();
1172     }
1173 
1174     /**
1175      * Returns a <code>BigDecimal</code> represented.
1176      *
1177      * @return 
1178      *    a <code>BigDecimal</code> <code>d</code> satisfying 
1179      *    {@link #create(Number, boolean) 
1180      *            create(d, true).this2BigDecimal().compareTo(d) == 0}. 
1181      */
1182     public final BigDecimal this2BigDecimal() {
1183 	//**** this does not work with trimmed mantissas
1184 	return new BigDecimal(this.sign + mantissa() + getExpWithE());
1185     }
1186 
1187     private String getExpWithE() {
1188 	return this.exponent.equals("") ? "" : EXP_CHAR + this.exponent;
1189     }
1190 
1191     /**
1192      * Returns a String representation of this real number. 
1193      * Formatting is determined by previous invocations of the methods 
1194      * {@link #trimInteger}, {@link #trimFraction} and {@link #trimExponent}. 
1195      *
1196      * @return 
1197      *    a <code>String</code> reflecting this representation 
1198      *    of a real number. 
1199      *    In front of the sign (which may be empty), 
1200      *    between the sign and the integer part, 
1201      *    between the fractional part 
1202      *    and the exponent or the end of the string 
1203      *    and also between the *****
1204      * @see #toStringDecomp
1205      */
1206     public final String toString() {
1207 	return 
1208 	    (this.sign   == SIGN_PLUS ? "" : this.sign) + 
1209 	    mantissa() + 
1210 	    (hasExponent() ? "e" : "") + exponent();
1211     }
1212 
1213     public final String toString(Desc desc) {
1214 
1215 	trimInteger (desc.lenI, ' ', desc.strictInteger);
1216 	trimFraction(desc.lenM - 
1217 		     desc.lenI, ' ', desc.fractionCutter);
1218 	trimExponent(desc.lenE, ' ', desc.strictExponent);
1219 
1220 	return 
1221 	    (this.sign   == SIGN_PLUS ? "" : this.sign) + 
1222 	    mantissa() + 
1223 	    (hasExponent() ? "E" : " ") + exponent();
1224     }
1225 
1226     /**
1227      * Returns a string showing the decomposition of the underlying real number 
1228      * into sign, mantissa and exponent. 
1229      *
1230      * @return a <code>String</code> value
1231      * @see #toString
1232      */
1233     public final String toStringDecomp() {
1234 	return 
1235 	    "sign:     " + this.sign + "\n" + 
1236 	    "integer:  " + this.integer + "\n" + 
1237 	    "fraction: " + this.fraction + "\n" + 
1238 	    "exponent: " + this.exponent;
1239     }
1240 }