Java API By Example, From Geeks To Geeks.

# Java > Open Source Codes > org > jscience > mathematics > numbers > Real

 `1 /*2  * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.3  * Copyright (C) 2006 - JScience (http://jscience.org/)4  * All rights reserved.5  * 6  * Permission to use, copy, modify, and distribute this software is7  * freely granted, provided that this notice is preserved.8  */9 package org.jscience.mathematics.numbers;10 11 import org.jscience.mathematics.structures.Field;12 13 import javolution.lang.MathLib;14 import javolution.context.LocalContext;15 import javolution.text.Text;16 import javolution.text.TypeFormat;17 import javolution.xml.XMLFormat;18 import javolution.xml.stream.XMLStreamException;19 20 /**21  *

This class represents a real number of arbitrary precision with 22  * known/guaranteed uncertainty. A real number consists of a 23  * {@link #getMantissa mantissa}, a maximum {@link #getError error} 24  * (on the mantissa) and a decimal {@link #getExponent exponent}: 25  * ((mantissa ± error) · 10exponent).

26  * 27  *

Reals number can be {@link #isExact exact} (e.g. integer values 28  * scaled by a power of ten). Exactness is maintained for29  * {@link org.jscience.mathematics.structures.Ring Ring} operations30  * (e.g. addition, multiplication), but typically lost when a 31  * multiplicative {@link #inverse()} is calculated. The minimum 32  * precision for an exact number is set by 33  * {@link #setExactMinimumPrecision(int)} ({@link 34  * javolution.context.LocalContext context local} setting, default35  * 19 digits).

36  * 37  *

The actual {@link #getPrecision precision} and {@link #getAccuracy 38  * accuracy} of any real number is available and guaranteed 39  * (the true/exact value is always within the precision/accuracy range).

40  * 41  *

Operations on instances of this class are quite fast 42  * as information substantially below the precision level (aka noise)43  * is not processed/stored. There is no limit on a real precision44  * but precision degenerates (due to numeric errors) and calculations 45  * accelerate as more and more operations are performed.

46  * 47  *

Instances of this class can be utilized to find approximate 48  * solutions to linear equations using the 49  * {@link org.jscience.mathematics.vectors.Matrix Matrix} class for which50  * high-precision reals is often required, the primitive type51  * double being not accurate enough to resolve equations 52  * when the matrix's size exceeds 100x100. Furthermore, even for small 53  * matrices the "qualified" result is indicative of possible system 54  * singularities.

55  * 56  * @author Jean-Marie Dautelle57  * @version 3.3, January 8, 200658  * @see 59  * Wikipedia: Real number60  */61 public final class Real extends Number implements Field {62 63     /**64      * Holds the default XML representation for real numbers.65      * This representation consists of a simple value attribute66      * holding the {@link #toText() textual} representation.67      */68     protected static final XMLFormat XML = new XMLFormat(Real.class) {69         70         @Override 71         public Real newInstance(Class cls, InputElement xml) throws XMLStreamException {72             return Real.valueOf(xml.getAttribute("value"));73         }74         75         public void write(Real real, OutputElement xml) throws XMLStreamException {76              xml.setAttribute("value", real.toText());77          }78 79          public void read(InputElement xml, Real real) {80              // Nothing to do, immutable.81 }82      };83 84     /** 85      * Holds a Not-a-Number instance (infinite error). 86      */87     public static final Real NaN = new Real(); // Unique (0 ± 1E2147483647)88 static {89         NaN._mantissa = LargeInteger.ZERO;90         NaN._error = LargeInteger.ONE;91         NaN._exponent = Integer.MAX_VALUE;92     }93 94     /** 95      * Holds the exact ZERO instance. 96      */97     public static final Real ZERO = new Real();98     static {99         ZERO._mantissa = LargeInteger.ZERO;100         ZERO._error = LargeInteger.ZERO;101         ZERO._exponent = 0;102     }103 104     /** 105      * Holds the exact ONE instance. 106      */107     public static final Real ONE = new Real();108     static {109         ZERO._mantissa = LargeInteger.ONE;110         ZERO._error = LargeInteger.ZERO;111         ZERO._exponent = 0;112     }113 114     /**115      * Holds local precision for exact number.116      */117     private static final LocalContext.Reference EXACT_PRECISION = 118         new LocalContext.Reference(new Integer (19));119 120     /**121      * The mantissa value.122      */123     private LargeInteger _mantissa;124     125     /**126      * The mantissa error (0 for exact number).127      */128     private LargeInteger _error;129 130     /**131      * The decimal exponent.132      */133     private int _exponent;134 135     /**136      * Default constructor.137      */138     private Real() {139     }140 141     /**142      * Returns the {@link javolution.context.LocalContext local} minimum 143      * precision when exact numbers have to be approximated.144      * 145      * @return the minimum number of digits assumed exact for {@link #isExact 146      * exact} real numbers.147      */148     public static int getExactMinimumPrecision() {149         return EXACT_PRECISION.get();150     }151 152     /**153      * Sets the {@link javolution.context.LocalContext local} minimum precision154      * when exact numbers have to be approximated.155      * 156      * @param precision the minimum number of digits assumed exact for 157      * {@link #isExact exact} numbers.158      */159     public static void setExactMinimumPrecision(int precision) {160         EXACT_PRECISION.set(precision);161     }162     163     /**164      * Returns a real having the specified mantissa, error and exponent values.165      * If the error is 0, the real is assumed exact. 166      * For example:[code]167      * 168      * // x = 0.0 ± 0.01 169      * Real x = Real.valueOf(LargeInteger.ZERO, LargeInteger.ONE, -2);170      * 171      * // y = -12.3 exact 172      * Real y = Real.valueOf(LargeInteger.valueOf("-123"), LargeInteger.ZERO, -1);173      * 174      * [/code]175      * 176      * @param mantissa this real mantissa.177      * @param error the maximum error on the mantissa.178      * @param exponent the decimal exponent.179      * @return (mantissa ± error)·10exponent)180      * @throws IllegalArgumentException if error < 0181      */182     public static Real valueOf(LargeInteger mantissa, LargeInteger error,183             int exponent) {184         if (error.isNegative()) 185             throw new IllegalArgumentException ("Error cannot be negative");186         Real real = FACTORY.object();187         real._mantissa = mantissa;188         real._error = error;189         real._exponent = exponent;190         return real;191     }192 193     /**194      * Returns the real number (inexact except for 0.0) 195      * corresponding to the specified double value. 196      * The error is derived from the inexact representation of 197      * double values intrinsic to the 64 bits IEEE 754 format.198      * 199      * @param doubleValue the double value to convert.200      * @return the corresponding real number.201      */202     public static Real valueOf(double doubleValue) {203         if (doubleValue == 0.0) 204             return Real.ZERO;205         // Find the exponent e such as: value == x.xxx * 10^e206 int e = MathLib.floorLog10(doubleValue) - 18 + 1; // 18 digits mantissa.207 long mantissa = MathLib.toLongPow10(doubleValue, -e); 208         int error = (int) MathLib.toLongPow10(Math.ulp(doubleValue), -e) + 1;209         return 210            Real.valueOf(LargeInteger.valueOf(mantissa), LargeInteger.valueOf(error), e);211     }212 213 214     /**215      * Returns the exact real number corresponding to the specified 216      * long value (convenience method). 217      * 218      * @param longValue the exact long value.219      * @return Real.valueOf(LargeInteger.valueOf(longValue), 0, 0)220      */221     public static Real valueOf(long longValue) {222          return Real.valueOf(LargeInteger.valueOf(longValue), LargeInteger.ZERO, 0);223     }224 225     /**226      * Returns the real for the specified character sequence.227      * If the precision is not specified (using the ± symbol), 228      * the real is supposed exact. Example of valid character sequences:229      *
• "1.2E3" (1200 exact)
• 230      *
• "1.2E3±1E-2" (1200 ± 0.01)
• 231      * 232      * @param chars the character sequence.233      * @return the corresponding real number.234      * @throws NumberFormatException if the character sequence does not contain235      * a parsable real.236      */237     public static Real valueOf(CharSequence chars) throws NumberFormatException {238         Text txt = Text.valueOf(chars); // TODO Use TextFormat...239 if ((txt.length() == 3) && (txt.indexOf("NaN", 0) == 0)) 240             return NaN;241         if (txt.equals("0")) return ZERO;242         int exponentIndex = txt.indexOf("E", 0);243         if (exponentIndex >= 0) {244             int exponent = TypeFormat.parseInt(txt.subtext(245                     exponentIndex + 1, txt.length()));246             Real r = valueOf(txt.subtext(0, exponentIndex));247             if (r == ZERO) 248                 return valueOf(LargeInteger.ZERO, LargeInteger.ONE, exponent);249             r._exponent += exponent;250             return r;251         }252         Real real = FACTORY.object();253         int errorIndex = txt.indexOf("±", 0);254         if (errorIndex >= 0) {255             real._mantissa = LargeInteger.valueOf(txt.subtext(0,256                     errorIndex));257             real._error = LargeInteger.valueOf(txt.subtext(258                     errorIndex + 1, txt.length()));259             if (real._error.isNegative()) 260                 throw new NumberFormatException (chars261                         + " not parsable (error cannot be negative)");262             real._exponent = 0;263             return real;264         }265         int decimalPointIndex = txt.indexOf(".", 0);266         if (decimalPointIndex >= 0) {267             LargeInteger integer = LargeInteger.valueOf(txt.subtext(0,268                     decimalPointIndex));269             LargeInteger fraction = LargeInteger.valueOf(txt.subtext(270                     decimalPointIndex + 1, txt.length()));271             int fractionDigits = chars.length() - decimalPointIndex - 1;272             real._mantissa = integer.isNegative() ?273                     integer.times10pow(fractionDigits).minus(fraction) :274                     integer.times10pow(fractionDigits).plus(fraction);275             real._error = LargeInteger.ZERO;276             real._exponent = -fractionDigits;277             return real;278         } else {279             real._mantissa = LargeInteger.valueOf(chars);280             real._error = LargeInteger.ZERO;281             real._exponent = 0;282             return real;283         }284     }285     286     /**287      * Returns this real mantissa.288      * 289      * @return the mantissa.290      */291     public LargeInteger getMantissa() {292         return _mantissa;293     }294 295     /**296      * Returns the maximum error (positive) on this real mantissa.297      * 298      * @return the maximum error on the mantissa.299      */300     public LargeInteger getError() {301         return _error;302     }303 304     /**305      * Returns the exponent of the power of 10 multiplier.306      * 307      * @return the decimal exponent.308      */309     public int getExponent() {310         return _exponent;311     }312 313     /**314      * Indicates if this real number is exact ({@link #getError() error} 315      * == 0).316      *317      * @return getError() == 0318      */319     public boolean isExact() {320         return _error.isZero();321     }322 323     /**324      * Returns the number of decimal digits guaranteed exact which appear to325      * the right of the decimal point (absolute error).326      *327      * @return a measure of the absolute error of this real number.328      */329     public int getAccuracy() {330         if (_error.isZero()) return Integer.MAX_VALUE;331         if (this == NaN) return Integer.MIN_VALUE;332         return -_exponent - _error.digitLength();333     }334 335     /**336      * Returns the total number of decimal digits guaranteed exact337      * (relative error).338      *339      * @return a measure of the relative error of this real number.340      */341     public final int getPrecision() {342         if (_error.isZero()) return Integer.MAX_VALUE;343         if (this == NaN) return Integer.MIN_VALUE;344         return _mantissa.digitLength() - _error.digitLength();345     }346 347     /**348      * Indicates if this real is greater than zero.349      * 350      * @return this > 0351      */352     public boolean isPositive() {353         return _mantissa.isPositive();354     }355 356     /**357      * Indicates if this real is less than zero.358      * 359      * @return this < 0360      */361     public boolean isNegative() {362         return _mantissa.isNegative();363     }364 365     /**366      * Indicates if this real is Not-a-Number (unbounded value interval).367      * 368      * @return true if this number has unbounded value interval;369      * false otherwise.370      */371     public boolean isNaN() {372         return this == NaN;373     }374 375     /**376      * Indicates if this real approximates the one specified. 377      * This method takes into account possible errors (e.g. numeric378      * errors) to make this determination.379      * 380      *

Note: This method returns true if this or 381      * that {@link #isNaN} (basically Not-A-Number 382      * approximates anything).

383      *384      * @param that the real to compare with.385      * @return this ≈ that386      */387     public boolean approximates(Real that) {388         Real diff = this.minus(that);389         if (diff == NaN) return false;390         return diff._error.isLargerThan(diff._mantissa);391     }392 393     /**394      * Converts this real to a {@link LargeInteger} instance. 395      * Any fractional part of this real is discarded.396      * 397      * @return the integer part of this real.398      * @throws ArithmeticException if this.isNaN()399      */400     public LargeInteger toLargeInteger() {401         if (this == NaN) 402             throw new ArithmeticException ("Cannot convert NaN to integer value");403         return _mantissa.times10pow(_exponent);404     }405 406     /**407      * Returns the negation of this real number.408      * 409      * @return -this.410      */411     public Real opposite() {412         if (this == NaN) return NaN;413         Real real = FACTORY.object();414         real._mantissa = _mantissa.opposite();415         real._exponent = _exponent;416         real._error = _error;417         return real;418     }419 420     /**421      * Returns the sum of this real number with the one specified.422      * 423      * @param that the real to be added.424      * @return this + that.425      */426     public Real plus(Real that) {427         if ((this == NaN) || (that == NaN)) return NaN;428         if (this._exponent > that._exponent)429             return that.plus(this); // Adds to the real with smallest exponent. 430 int scale = that._exponent - this._exponent; // >= 0431 Real real = (Real) FACTORY.object();432         real._exponent = _exponent;433         real._mantissa = this._mantissa.plus(that._mantissa.times10pow(scale));434         real._error = this._error.plus(that._error.times10pow(scale));435         return real;436     }437     438     /**439      * Returns the difference between this real number and the one440      * specified.441      * 442      * @param that the real to be subtracted.443      * @return this - that.444      */445     public Real minus(Real that) {446         return this.plus(that.opposite());447     }448 449     /**450      * Returns the product of this real number with the specified 451      * long multiplier.452      * 453      * @param multiplier the long multiplier.454      * @return this · multiplier.455      */456     public Real times(long multiplier) {457         if (this == NaN) return NaN;458         Real real = FACTORY.object();459         real._exponent = this._exponent;460         real._mantissa = this._mantissa.times(multiplier);461         real._error = this._error.times(multiplier);462         return real;463     }464 465     /**466      * Returns the product of this real number with the one specified.467      * 468      * @param that the real multiplier.469      * @return this · that.470      */471     public Real times(Real that) {472         if ((this == NaN) || (that == NaN)) return NaN;473         long exp = ((long) this._exponent) + that._exponent;474         if (exp > Integer.MAX_VALUE || (exp < Integer.MIN_VALUE)) 475             return NaN; // Exponent overflow.476 LargeInteger thisMin = this._mantissa.minus(this._error);477         LargeInteger thisMax = this._mantissa.plus(this._error);478         LargeInteger thatMin = that._mantissa.minus(that._error);479         LargeInteger thatMax = that._mantissa.plus(that._error);480         LargeInteger min, max;481         if (thisMin.compareTo(thisMax.opposite()) > 0) {482             if (thatMin.compareTo(thatMax.opposite()) > 0) {483                 min = thisMin.times(thatMin);484                 max = thisMax.times(thatMax);485             } else {486                 min = thisMax.times(thatMin);487                 max = thisMin.times(thatMax);488             }489         } else {490             if (thatMin.compareTo(thatMax.opposite()) > 0) {491                 min = thisMin.times(thatMax);492                 max = thisMax.times(thatMin);493             } else {494                 min = thisMax.times(thatMax);495                 max = thisMin.times(thatMin);496             }497         }498         Real real = FACTORY.object();499         real._exponent = (int) exp;500         real._mantissa = min.plus(max).shiftRight(1);501         real._error = max.minus(min);502         return real;503     }504     505     /**506      * Returns this real number divided by the specified int507      * divisor. 508      * 509      * @param divisor the int divisor.510      * @return this / divisor511      */512     public Real divide(long divisor) {513         return this.divide(Real.valueOf(divisor));514     }515     516     /**517      * Returns this real number divided by the one specified.518      * 519      * @param that the real divisor.520      * @return this / that.521      * @throws ArithmeticException if that.equals(ZERO)522      */523     public Real divide(Real that) {524         return this.times(that.inverse());525     }526 527     /**528      * Returns the reciprocal (or inverse) of this real number.529      *530      * @return 1 / this.531      */532     public Real inverse() {533         if ((this == NaN) || (this == ZERO))534             return NaN;535         if (this.isExact()) return this.toInexact().inverse();536         LargeInteger thisMin = this._mantissa.minus(this._error);537         LargeInteger thisMax = this._mantissa.plus(this._error);538         if (thisMin.isNegative() && thisMax.isPositive()) // Encompasses 0539 return NaN;540         int digits = MathLib.max(thisMin.digitLength(), thisMax.digitLength());541         long exp = ((long) -this._exponent) - digits - digits;542         if ((exp > Integer.MAX_VALUE || (exp < Integer.MIN_VALUE))) 543             return NaN; // Exponent overflow.544 LargeInteger min = div(2 * digits, thisMax);545         LargeInteger max = div(2 * digits, thisMin);546         Real real = (Real) FACTORY.object();547         real._exponent = (int) exp;548         real._mantissa = min.plus(max).shiftRight(1);549         real._error = max.minus(min).plus(LargeInteger.ONE);550         return real;551     }552     private static LargeInteger div(int exp, LargeInteger mantissa) {553         int expBitLength = (int) (exp * DIGITS_TO_BITS);554         int precision = expBitLength - mantissa.bitLength() + 1;555         LargeInteger reciprocal = mantissa.inverseScaled(precision);556         LargeInteger result = reciprocal.times10pow(exp);557         return result.shiftRight(expBitLength + 1);558     }559     private static final double DIGITS_TO_BITS = MathLib.LOG10 / MathLib.LOG2;560     561     private Real toInexact() {562         int precision = Real.getExactMinimumPrecision();563         Real z = FACTORY.object();564         z._mantissa = _mantissa.times10pow(precision);565         z._error = LargeInteger.ONE;566         z._exponent = _exponent - precision;567         return z;568     }569     570     /**571      * Returns the absolute value of this real number.572      * 573      * @return |this|.574      */575     public Real abs() {576         return _mantissa.isNegative() ? this.opposite() : this;577     }578 579     /**580      * Compares the absolute value of two real numbers.581      *582      * @param that the real number to be compared with.583      * @return |this| > |that|584      */585     public boolean isLargerThan(Real that) {586         return this.abs().compareTo(that.abs()) > 0;587     }588 589     /**590      * Returns the square root of this real number, the more accurate is this 591      * real number, the more accurate the square root. 592      * 593      * @return the positive square root of this real number.594      */595     public Real sqrt() {596         if (this == NaN) return NaN;597         if (this.isExact()) return this.toInexact().sqrt();598         LargeInteger thisMin = this._mantissa.minus(this._error);599         LargeInteger thisMax = this._mantissa.plus(this._error);600         if (thisMin.isNegative()) return NaN;601         int exponent = _exponent >> 1;602         if ((_exponent & 1) == 1) { // Odd exponent.603 thisMin = thisMin.times10pow(1);604             thisMax = thisMax.times10pow(1);605         }606         LargeInteger minSqrt = thisMin.sqrt();607         LargeInteger maxSqrt = thisMax.sqrt().plus(LargeInteger.ONE);608         LargeInteger sqrt = minSqrt.plus(maxSqrt).shiftRight(1);609         Real z = FACTORY.object();610         z._mantissa = sqrt;611         z._error = maxSqrt.minus(sqrt);612         z._exponent = exponent;613         return z;614     }615     616     /**617      * Returns the decimal text representation of this number.618      *619      * @return the text representation of this number.620      */621     public Text toText() {622         if (this == NaN) return Text.valueOf("NaN");623         if (this == ZERO) return Text.valueOf("0");624         int errorDigits = _error.digitLength();625         LargeInteger m = (_mantissa.isPositive()) ? _mantissa.plus(FIVE626                 .times10pow(errorDigits - 1)) : _mantissa.plus(MINUS_FIVE627                 .times10pow(errorDigits - 1));628         m = m.times10pow(-errorDigits);629         int exp = _exponent + errorDigits;630         Text txt = m.toText();631         int digits = (m.isNegative()) ? txt.length() - 1 : txt.length();632         if (digits > 1) {633             if ((exp < 0) && (-exp < digits)) {634                 txt = txt.insert(txt.length() + exp, Text.valueOf('.'));635             } else { // Scientific notation.636 txt = txt.insert(txt.length() - digits + 1, Text.valueOf('.'));637                 txt = txt.concat(Text.valueOf('E')).concat(Text.valueOf(exp + digits - 1));638             }639         } else {640             txt = txt.concat(Text.valueOf('E')).concat(Text.valueOf(exp));641         }642         return txt;643     }644     private static final LargeInteger FIVE = LargeInteger.valueOf(5).moveHeap();645     private static final LargeInteger MINUS_FIVE = LargeInteger.valueOf(-5).moveHeap();646 647     /**648      * Compares this real number against the specified object.649      * 650      *

Note: This method returns true if this or 651      * that {@link #isNaN is Not-A-Number}, even though652      * Double.NaN == Double.NaN has the value653      * false.

654      *655      * @param that the object to compare with.656      * @return true if the objects are two reals with same 657      * mantissa, error and exponent;false otherwise.658      */659     public boolean equals(Object that) {660         if (this == that) return true;661         if (!(that instanceof Real)) 662             return false;663         Real thatReal = (Real) that;664         return this._mantissa.equals(thatReal._mantissa) && this._error.equals(thatReal._error)665               && (this._exponent == thatReal._exponent);666     }667 668     /**669      * Returns the hash code for this real number.670      * 671      * @return the hash code value.672      */673     public int hashCode() {674         return _mantissa.hashCode() + _error.hashCode() + _exponent * 31;675     }676 677     /**678      * Returns the value of this real number as a long.679      * 680      * @return the numeric value represented by this real after conversion681      * to type long.682      */683     public long longValue() {684         return (long) doubleValue();685     }686 687     /**688      * Returns the value of this real number as a double.689      * 690      * @return the numeric value represented by this real after conversion691      * to type double.692      */693     public double doubleValue() {694         if (this == NaN) return Double.NaN;695         if (this == ZERO) return 0.0;696         // Shift the mantissa to a >18 digits integer (long compatible).697 int nbrDigits = _mantissa.digitLength();698         int digitShift = nbrDigits - 18;699         long reducedMantissa = _mantissa.times10pow(-digitShift).longValue();700         int exponent = _exponent + digitShift;701         return MathLib.toDoublePow10(reducedMantissa, exponent);702     }703 704     /**705      * Compares two real numbers numerically.706      * 707      * @param that the real to compare with.708      * @return -1, 0 or 1 as this real is numerically less than, equal to,709      * or greater than that.710      * @throws ClassCastException that is not a {@link Real}.711      */712     public int compareTo(Real that) {713         Real diff = this.minus(that);714         if (diff.isPositive()) {715             return 1;716         } else if (diff.isNegative()) {717             return -1;718         } else {719             return 0;720         }721     }722 723     // Moves additional real-time members.724 public boolean move(ObjectSpace os) {725         if (super.move(os)) {726             _mantissa.move(os);727             _error.move(os);728             return true;729         }730         return false;731     }732 733     /**734      * Holds the factory constructing real instances.735      */736     private static final Factory FACTORY = new Factory() {737 738         public Real create() {739             return new Real();740         }741     };742 743     private static final long serialVersionUID = 1L;744 745 }` Popular Tags