001/* 002 * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences. 003 * Copyright (C) 2007 - JScience (http://jscience.org/) 004 * All rights reserved. 005 * 006 * Permission to use, copy, modify, and distribute this software is 007 * freely granted, provided that this notice is preserved. 008 */ 009package org.jscience.mathematics.number; 010 011import org.jscience.mathematics.structure.Field; 012 013import javolution.context.LocalContext; 014import javolution.context.ObjectFactory; 015import javolution.lang.MathLib; 016import javolution.text.Text; 017import javolution.text.TextBuilder; 018import javolution.xml.XMLFormat; 019import javolution.xml.stream.XMLStreamException; 020 021/** 022 * <p> This class represents a floating point number of arbitrary precision. 023 * A floating point number consists of a {@link #getSignificand significand} 024 * and a decimal {@link #getExponent exponent}: 025 * (<code>significand · 10<sup>exponent</sup></code>).</p> 026 * 027 * <p> Unlike {@link Real} numbers, no calculation error is performed on 028 * floating point instances but the number of digits used during 029 * calculations can be specified (see {@link #setDigits(int)}). The 030 * largest the number of digits, the smallest the numeric error. 031 * For example:[code] 032 * FloatingPoint two = FloatingPoint.valueOf(2); 033 * FloatingPoint.setDigits(30); // 30 digits calculations. 034 * System.out.println(two.sqrt()); 035 * > 0.141421356237309504880168872420E1 036 * [/code]</p> 037 * 038 * <p> Instances of this class are immutable and can be used to find 039 * accurate solutions to linear equations with the {@link 040 * org.jscience.mathematics.vector.Matrix Matrix} class.</p> 041 * 042 * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a> 043 * @version 4.1, June 8, 2007 044 * @see <a href="http://en.wikipedia.org/wiki/Floating_point"> 045 * Wikipedia: Floating point</a> 046 */ 047public final class FloatingPoint extends Number<FloatingPoint> implements 048 Field<FloatingPoint> { 049 050 /** 051 * Holds the default XML representation for floating point numbers. 052 * This representation consists of a simple <code>value</code> attribute 053 * holding the {@link #toText() textual} representation. 054 */ 055 static final XMLFormat<FloatingPoint> XML = new XMLFormat<FloatingPoint>( 056 FloatingPoint.class) { 057 058 @Override 059 public FloatingPoint newInstance(Class<FloatingPoint> cls, 060 InputElement xml) throws XMLStreamException { 061 return FloatingPoint.valueOf(xml.getAttribute("value")); 062 } 063 064 public void write(FloatingPoint FloatingPoint, OutputElement xml) 065 throws XMLStreamException { 066 xml.setAttribute("value", FloatingPoint.toText()); 067 } 068 069 public void read(InputElement xml, FloatingPoint FloatingPoint) { 070 // Nothing to do, immutable. 071 } 072 }; 073 074 /** 075 * Holds the factory constructing floating point instances. 076 */ 077 private static final ObjectFactory<FloatingPoint> FACTORY = new ObjectFactory<FloatingPoint>() { 078 079 protected FloatingPoint create() { 080 return new FloatingPoint(); 081 } 082 }; 083 084 /** 085 * The floating point instance representing the additive identity. 086 */ 087 public static final FloatingPoint ZERO = new FloatingPoint( 088 LargeInteger.ZERO, 0); 089 090 /** 091 * The floating point instance representing the multiplicative identity. 092 */ 093 public static final FloatingPoint ONE = new FloatingPoint(LargeInteger.ONE, 094 0); 095 096 /** 097 * The Not-a-Number instance (unique). 098 */ 099 public static final FloatingPoint NaN = new FloatingPoint( 100 LargeInteger.ZERO, Integer.MAX_VALUE); 101 102 /** 103 * Holds the number of digits to be used (default 20 digits). 104 */ 105 private static final LocalContext.Reference<Integer> DIGITS = new LocalContext.Reference<Integer>( 106 20); 107 108 /** 109 * Holds the significand value. 110 */ 111 private LargeInteger _significand; 112 113 /** 114 * Holds the power of 10 exponent. 115 */ 116 private int _exponent; 117 118 /** 119 * Default constructor. 120 */ 121 private FloatingPoint() { 122 } 123 124 /** 125 * Creates a floating point number for the specified significand and 126 * exponent. 127 * 128 * @param significand the significand. 129 * @param exponent the power of two exponent. 130 */ 131 private FloatingPoint(LargeInteger significand, int exponent) { 132 _significand = significand; 133 _exponent = exponent; 134 } 135 136 /** 137 * Returns the floating point number for the specified {@link 138 * LargeInteger} significand and power of two exponent. 139 * 140 * @param significand the significand value. 141 * @param exponent the power of two exponent. 142 * @return <code>(significand · 2<sup>exponent</sup></code> 143 */ 144 public static FloatingPoint valueOf(LargeInteger significand, int exponent) { 145 FloatingPoint fp = FACTORY.object(); 146 fp._significand = significand; 147 fp._exponent = exponent; 148 return fp; 149 } 150 151 /** 152 * Returns the floating point number for the specified <code>long</code> 153 * significand and power of two exponent (convenience method). 154 * 155 * @param significand the significand value. 156 * @param exponent the power of two exponent. 157 * @return <code>(significand · 2<sup>exponent</sup></code> 158 */ 159 public static FloatingPoint valueOf(long significand, int exponent) { 160 FloatingPoint fp = FACTORY.object(); 161 fp._significand = LargeInteger.valueOf(significand); 162 fp._exponent = exponent; 163 return fp; 164 } 165 166 /** 167 * Returns the floating point number for the specified <code>long</code> 168 * value (convenience method). 169 * 170 * @param longValue the <code>long</code> value. 171 * @return <code>FloatingPoint.valueOf(longValue, 0)</code> 172 */ 173 public static FloatingPoint valueOf(long longValue) { 174 return FloatingPoint.valueOf(longValue, 0); 175 } 176 177 /** 178 * Returns the floating point number for the specified <code>double</code> 179 * value (convenience method). 180 * 181 * @param doubleValue the <code>double</code> value. 182 * @return <code>FloatingPoint.valueOf(longValue, 0)</code> 183 */ 184 public static FloatingPoint valueOf(double doubleValue) { 185 if (doubleValue == 0.0) 186 return FloatingPoint.ZERO; 187 if (Double.isNaN(doubleValue) || Double.isInfinite(doubleValue)) 188 return FloatingPoint.NaN; 189 190 // Find the exponent e such as: value == x.xxx * 10^e 191 int e = MathLib.floorLog10(doubleValue) - 18 + 1; // 18 digits significand. 192 long significand = MathLib.toLongPow10(doubleValue, -e); 193 return FloatingPoint.valueOf(significand, e); 194 } 195 196 /** 197 * Returns the floating point number for the specified character sequence. 198 * The number of digits 199 * 200 * @param chars the character sequence. 201 * @return the corresponding FloatingPoint number. 202 */ 203 public static FloatingPoint valueOf(CharSequence chars) { 204 // Use same format as Real. 205 Real real = Real.valueOf(chars); 206 if (real.getError() != 0) 207 throw new IllegalArgumentException("No error allowed"); 208 return FloatingPoint.valueOf(real.getSignificand(), real.getExponent()); 209 } 210 211 /** 212 * Returns the {@link javolution.context.LocalContext local} number of 213 * digits used during calculations (default 20 digits). 214 * 215 * @return the number of digits. 216 */ 217 public static int getDigits() { 218 return DIGITS.get(); 219 } 220 221 /** 222 * Sets the {@link javolution.context.LocalContext local} number of digits 223 * to be used during calculations. 224 * 225 * @param digits the number of digits. 226 * @throws IllegalArgumentException if <code>digits <= 0</code> 227 */ 228 public static void setDigits(int digits) { 229 if (digits <= 0) 230 throw new IllegalArgumentException("digits: " + digits 231 + " has to be greater than 0"); 232 DIGITS.set(digits); 233 } 234 235 /** 236 * Returns the significand value. 237 * 238 * @return this floating point significand. 239 */ 240 public LargeInteger getSignificand() { 241 return _significand; 242 } 243 244 /** 245 * Returns the decimal exponent. 246 * 247 * @return this floating point decimal exponent. 248 */ 249 public int getExponent() { 250 return _exponent; 251 } 252 253 /** 254 * Returns the closest integer to this floating point number. 255 * 256 * @return this floating point rounded to the nearest integer. 257 */ 258 public LargeInteger round() { 259 if (this == NaN) 260 throw new ArithmeticException("Cannot convert NaN to integer value"); 261 LargeInteger half = LargeInteger.FIVE.times10pow(_exponent - 1); 262 return isNegative() ? _significand.minus(half).times10pow(_exponent) 263 : _significand.plus(half).times10pow(_exponent); 264 } 265 266 /** 267 * Returns the opposite of this floating point number. 268 * 269 * @return <code>-this</code>. 270 */ 271 public FloatingPoint opposite() { 272 return FloatingPoint.valueOf(_significand.opposite(), _exponent); 273 } 274 275 /** 276 * Returns the sum of this floating point number with the one specified. 277 * 278 * @param that the floating point number to be added. 279 * @return <code>this + that</code>. 280 */ 281 public FloatingPoint plus(FloatingPoint that) { 282 if (this._exponent > that._exponent) 283 return that.plus(this); 284 int pow10Scaling = that._exponent - this._exponent; 285 LargeInteger thatScaled = that._significand.times10pow(pow10Scaling); 286 return FloatingPoint.valueOf(_significand.plus(thatScaled), _exponent) 287 .normalize(); 288 } 289 290 /** 291 * Returns the difference between this FloatingPoint number and the one 292 * specified. 293 * 294 * @param that the floating point number to be subtracted. 295 * @return <code>this - that</code>. 296 */ 297 public FloatingPoint minus(FloatingPoint that) { 298 if (this._exponent > that._exponent) 299 return that.plus(this); 300 int pow10Scaling = that._exponent - this._exponent; 301 LargeInteger thatScaled = that._significand.times10pow(pow10Scaling); 302 return FloatingPoint.valueOf(_significand.minus(thatScaled), _exponent) 303 .normalize(); 304 } 305 306 /** 307 * Returns the product of this floating point number with the specified 308 * <code>long</code> multiplier. 309 * 310 * @param multiplier the <code>long</code> multiplier. 311 * @return <code>this · multiplier</code>. 312 */ 313 public FloatingPoint times(long multiplier) { 314 return this.times(FloatingPoint.valueOf(multiplier)); 315 } 316 317 /** 318 * Returns the product of this floating point number with the one specified. 319 * 320 * @param that the floating point number multiplier. 321 * @return <code>this · that</code>. 322 */ 323 public FloatingPoint times(FloatingPoint that) { 324 return FloatingPoint.valueOf( 325 this._significand.times(that._significand), 326 this._exponent + that._exponent).normalize(); 327 } 328 329 /** 330 * Returns the inverse of this floating point number. 331 * 332 * @return <code>1 / this</code>. 333 * @throws ArithmeticException if <code>dividend.isZero()</code> 334 */ 335 public FloatingPoint inverse() { 336 if (_significand.isZero()) 337 return NaN; 338 int pow10 = DIGITS.get() + _significand.digitLength(); 339 LargeInteger dividend = LargeInteger.ONE.times10pow(pow10); 340 return FloatingPoint.valueOf(dividend.divide(_significand), 341 -pow10 - _exponent).normalize(); 342 } 343 344 /** 345 * Returns this floating point number divided by the one specified. 346 * 347 * @param that the FloatingPoint number divisor. 348 * @return <code>this / that</code>. 349 * @throws ArithmeticException if <code>that.equals(ZERO)</code> 350 */ 351 public FloatingPoint divide(FloatingPoint that) { 352 if (that._significand.isZero()) 353 return NaN; 354 int pow10 = DIGITS.get() + that._significand.digitLength(); 355 LargeInteger dividend = _significand.times10pow(pow10); 356 return FloatingPoint.valueOf(dividend.divide(that._significand), 357 this._exponent - pow10 - that._exponent).normalize(); 358 } 359 360 /** 361 * Returns the absolute value of this floating point number. 362 * 363 * @return <code>|this|</code>. 364 */ 365 public FloatingPoint abs() { 366 return FloatingPoint.valueOf(_significand.abs(), _exponent); 367 } 368 369 /** 370 * Returns the square root of this floating point number. 371 * 372 * @return the positive square root of this floating point number. 373 */ 374 public FloatingPoint sqrt() { 375 if (this == NaN) 376 return NaN; 377 int pow10 = DIGITS.get() * 2 - _significand.digitLength(); 378 int exp = _exponent - pow10; 379 if ((exp & 1) == 1) { // Ensures that exp is even. 380 pow10++; 381 exp--; 382 } 383 LargeInteger scaledValue = _significand.times10pow(pow10); 384 return FloatingPoint.valueOf(scaledValue.sqrt(), exp >> 1) 385 .normalize(); 386 } 387 388 /** 389 * Indicates if this floating point number is equal to zero. 390 * 391 * @return <code>this == 0</code> 392 */ 393 public boolean isZero() { 394 return _significand.isZero() && (this != NaN); 395 } 396 397 /** 398 * Indicates if this floating point number is greater than zero. 399 * 400 * @return <code>this > 0</code> 401 */ 402 public boolean isPositive() { 403 return _significand.isPositive(); 404 } 405 406 /** 407 * Indicates if this rational number is less than zero. 408 * 409 * @return <code>this < 0</code> 410 */ 411 public boolean isNegative() { 412 return _significand.isNegative(); 413 } 414 415 /** 416 * Indicates if this floating point is Not-a-Number. 417 * 418 * @return <code>true</code> if this number has unbounded value; 419 * <code>false</code> otherwise. 420 */ 421 public boolean isNaN() { 422 return this == NaN; 423 } 424 425 /** 426 * Compares the absolute value of two FloatingPoint numbers. 427 * 428 * @param that the FloatingPoint number to be compared with. 429 * @return <code>|this| > |that|</code> 430 */ 431 public boolean isLargerThan(FloatingPoint that) { 432 return this.abs().compareTo(that.abs()) > 0; 433 } 434 435 /** 436 * Returns the decimal text representation of this number. 437 * 438 * @return the text representation of this number. 439 */ 440 public Text toText() { 441 if (this == NaN) 442 return Text.valueOf("NaN"); 443 if (this._significand.isZero()) 444 return Text.valueOf("0.0"); 445 TextBuilder tb = TextBuilder.newInstance(); 446 LargeInteger m = _significand; 447 if (isNegative()) { 448 tb.append('-'); 449 m = m.opposite(); 450 } 451 tb.append("0."); 452 LargeInteger.DECIMAL_FORMAT.format(m, tb); 453 int exp = _exponent + m.digitLength(); 454 if (exp != 0) { 455 tb.append("E"); 456 tb.append(_exponent + m.digitLength()); 457 } 458 Text txt = tb.toText(); 459 TextBuilder.recycle(tb); 460 return txt; 461 } 462 463 /** 464 * Compares this floating point number against the specified object. 465 * 466 * @param that the object to compare with. 467 * @return <code>true</code> if the objects are the same; 468 * <code>false</code> otherwise. 469 */ 470 public boolean equals(Object that) { 471 if (that instanceof FloatingPoint) { 472 return this.minus((FloatingPoint) that).isZero(); 473 } else { 474 return false; 475 } 476 } 477 478 /** 479 * Returns the hash code for this floating point number. 480 * 481 * @return the hash code value. 482 */ 483 public int hashCode() { 484 return _significand.hashCode() - _exponent; 485 } 486 487 /** 488 * Returns the value of this floating point number as a <code>long</code>. 489 * 490 * @return the numeric value represented by this floating point 491 * after conversion to type <code>long</code>. 492 */ 493 public long longValue() { 494 Real real = Real.valueOf(_significand, 0, _exponent); 495 return real.longValue(); 496 } 497 498 /** 499 * Returns the value of this floating point number as a <code>double</code>. 500 * 501 * @return the numeric value represented by this FloatingPoint after conversion 502 * to type <code>double</code>. 503 */ 504 public double doubleValue() { 505 Real real = Real.valueOf(_significand, 0, _exponent); 506 return real.doubleValue(); 507 } 508 509 /** 510 * Compares two floating point number numerically. 511 * 512 * @param that the floating point number to compare with. 513 * @return -1, 0 or 1 as this FloatingPoint number is numerically less than, 514 * equal to, or greater than <code>that</code>. 515 */ 516 public int compareTo(FloatingPoint that) { 517 FloatingPoint diff = this.minus(that); 518 if (diff.isPositive()) { 519 return 1; 520 } else if (diff.isNegative()) { 521 return -1; 522 } else { 523 return 0; 524 } 525 } 526 527 /** 528 * Returns this floating point number after normalization based upon 529 * the number of digits. 530 * 531 * @return <code>this</code> 532 */ 533 private FloatingPoint normalize() { 534 int digits = FloatingPoint.getDigits(); 535 int thisDigits = this._significand.digitLength(); 536 if (thisDigits > digits) { // Scale down. 537 int pow10 = digits - thisDigits; // Negative. 538 _significand = _significand.times10pow(pow10); 539 long exponent = ((long) _exponent) - pow10; 540 if (exponent > Integer.MAX_VALUE) 541 return NaN; 542 if (exponent < Integer.MIN_VALUE) 543 return ZERO; 544 _exponent = (int) exponent; 545 } 546 return this; 547 } 548 549 @Override 550 public FloatingPoint copy() { 551 if (this == NaN) 552 return NaN; // Maintains unicity. 553 FloatingPoint r = FACTORY.object(); 554 r._significand = _significand.copy(); 555 r._exponent = _exponent; 556 return r; 557 } 558 559 private static final long serialVersionUID = 1L; 560}