All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apfloat.Apfloat Maven / Gradle / Ivy

The newest version!
/*
 * MIT License
 *
 * Copyright (c) 2002-2023 Mikko Tommila
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package org.apfloat;

import java.math.BigInteger;
import java.math.BigDecimal;
import java.io.PushbackReader;
import java.io.Writer;
import java.io.IOException;
import java.util.Formatter;
import static java.util.FormattableFlags.*;

import org.apfloat.spi.ApfloatImpl;

/**
 * Arbitrary precision floating-point number class.

* * Apfloat numbers are immutable.

* * A pitfall exists with the constructors {@link #Apfloat(float,long)} * and {@link #Apfloat(double,long)}. Since floats and * doubles are always represented internally in radix 2, the * conversion to any other radix usually causes round-off errors, and the * resulting apfloat won't be accurate to the desired number of digits.

* * For example, 0.3 can't be presented exactly in base 2. When * you construct an apfloat like new Apfloat(0.3f, 1000), the * resulting number won't be accurate to 1000 digits, but only to roughly 7 * digits (in radix 10). In fact, the resulting number will be something like * 0.30000001192092896...

* * If you want an exact representation of a floating-point primitive * (which is a rational number), you can use {@link Aprational#Aprational(double)}. * * @see ApfloatMath * * @version 1.11.1 * @author Mikko Tommila */ public class Apfloat extends Apcomplex implements Comparable { /** * Default constructor. To be used only by subclasses that * overload all needed methods. */ protected Apfloat() { } /** * Constructs an apfloat that is backed by the specified * ApfloatImpl object. * * @param impl The ApfloatImpl object backing this apfloat. */ protected Apfloat(ApfloatImpl impl) { assert (impl.precision() > 0); this.impl = impl; } /** * Constructs an apfloat from the specified string. * The default radix will be used.

* * The precision will be calculated from the number * of digits specified in the string. For example:

* * "0.1" will have a precision of 1 digit.
* "1.0" will have a precision of 2 digits.
* "100" will have a precision of 3 digits.
* * @param value The string representing the number. * * @exception NumberFormatException In case the number is invalid. */ public Apfloat(String value) throws NumberFormatException, ApfloatRuntimeException { this(ApfloatHelper.createApfloat(value, false)); } /** * Constructs an apfloat from the specified string and precision. * The default radix will be used. * * @param value The string representing the number. * @param precision The precision of the number. * * @exception NumberFormatException In case the number is invalid. * @exception IllegalArgumentException In case the precision is invalid. */ public Apfloat(String value, long precision) throws NumberFormatException, IllegalArgumentException, ApfloatRuntimeException { this(ApfloatHelper.createApfloat(value, precision, false)); } /** * Constructs an apfloat from the specified string, precision and radix.

* * Note that it's impossible to construct apfloats with a specified exponent * and with radix >= 14, since the characters 'e' and 'E' will be treated as * digits of the mantissa.

* * For example, in radix 10, "1e5" means the decimal number 100000. But in * radix 16, "1e5" means the decimal number 485. * * @param value The string representing the number. * @param precision The precision of the number. * @param radix The radix of the number. * * @exception NumberFormatException In case the number is invalid. * @exception IllegalArgumentException In case the precision is invalid. */ public Apfloat(String value, long precision, int radix) throws NumberFormatException, IllegalArgumentException, ApfloatRuntimeException { this(ApfloatHelper.createApfloat(value, precision, radix, false)); } /** * Constructs an apfloat from the specified long. * The default radix will be used. The precision of the number * will be {@link #INFINITE}. * * @param value The value of the number. * * @exception NumberFormatException In case the number is invalid. */ public Apfloat(long value) throws NumberFormatException, ApfloatRuntimeException { this(ApfloatHelper.createApfloat(value)); } /** * Constructs an apfloat from the specified long * and precision. The default radix will be used. * * @param value The value of the number. * @param precision The precision of the number. * * @exception NumberFormatException In case the number is invalid. * @exception IllegalArgumentException In case the precision is invalid. */ public Apfloat(long value, long precision) throws NumberFormatException, IllegalArgumentException, ApfloatRuntimeException { this(ApfloatHelper.createApfloat(value, precision)); } /** * Constructs an apfloat from the specified long, * precision and radix. * * @param value The value of the number. * @param precision The precision of the number. * @param radix The radix of the number. * * @exception NumberFormatException In case the number is invalid. * @exception IllegalArgumentException In case the precision is invalid. */ public Apfloat(long value, long precision, int radix) throws NumberFormatException, IllegalArgumentException, ApfloatRuntimeException { this(ApfloatHelper.createApfloat(value, precision, radix)); } /** * Constructs an apfloat from the specified float. * The default radix will be used. The precision of the number * will be the precision of a float in the default * radix, for example in radix 10 the precision is 7 digits. * * @param value The value of the number. * * @exception NumberFormatException In case the number is invalid. */ public Apfloat(float value) throws NumberFormatException, ApfloatRuntimeException { this(ApfloatHelper.createApfloat(value)); } /** * Constructs an apfloat from the specified float * and precision. The default radix will be used.

* * Note that the resulting apfloat won't accurately represent the given * float value to more than the default precision of a * float, for example in radix 10 the result is accurate to * only 7 digits. The rest of the digits are unspecified even if a greater * precision is specified. * * @param value The value of the number. * @param precision The precision of the number. * * @exception NumberFormatException In case the number is invalid. * @exception IllegalArgumentException In case the precision is invalid. */ public Apfloat(float value, long precision) throws NumberFormatException, IllegalArgumentException, ApfloatRuntimeException { this(ApfloatHelper.createApfloat(value, precision)); } /** * Constructs an apfloat from the specified float, * precision and radix.

* * Note that the resulting apfloat won't accurately represent the given * float value to more than the default precision of a * float, for example in radix 10 the result is accurate to * only 7 digits. The rest of the digits are unspecified even if a greater * precision is specified. * * @param value The value of the number. * @param precision The precision of the number. * @param radix The radix of the number. * * @exception NumberFormatException In case the number is invalid. * @exception IllegalArgumentException In case the precision is invalid. */ public Apfloat(float value, long precision, int radix) throws NumberFormatException, IllegalArgumentException, ApfloatRuntimeException { this(ApfloatHelper.createApfloat(value, precision, radix)); } /** * Constructs an apfloat from the specified double. * The default radix will be used. The precision of the number * will be the precision of a double in the default * radix, for example in radix 10 the precision is 16 digits. * * @param value The value of the number. * * @exception NumberFormatException In case the number is invalid. */ public Apfloat(double value) throws NumberFormatException, ApfloatRuntimeException { this(ApfloatHelper.createApfloat(value)); } /** * Constructs an apfloat from the specified double * and precision. The default radix will be used.

* * Note that the resulting apfloat won't accurately represent the given * double value to more than the default precision of a * double, for example in radix 10 the result is accurate to * only 16 digits. The rest of the digits are unspecified even if a greater * precision is specified.

* * In particular, this constructor does not work the same way as the * {@link BigDecimal#BigDecimal(double)} constructor. If you want that kind * of behavior then please use the {@link #Apfloat(BigDecimal, long)} * constructor. * * @param value The value of the number. * @param precision The precision of the number. * * @exception NumberFormatException In case the number is invalid. * @exception IllegalArgumentException In case the precision is invalid. */ public Apfloat(double value, long precision) throws NumberFormatException, IllegalArgumentException, ApfloatRuntimeException { this(ApfloatHelper.createApfloat(value, precision)); } /** * Constructs an apfloat from the specified double, * precision and radix.

* * Note that the resulting apfloat won't accurately represent the given * double value to more than the default precision of a * double, for example in radix 10 the result is accurate to * only 16 digits. The rest of the digits are unspecified even if a greater * precision is specified.

* * In particular, this constructor does not work the same way as the * {@link BigDecimal#BigDecimal(double)} constructor. If you want that kind * of behavior then please use the {@link #Apfloat(BigDecimal, long)} * constructor. * * @param value The value of the number. * @param precision The precision of the number. * @param radix The radix of the number. * * @exception NumberFormatException In case the number is invalid. * @exception IllegalArgumentException In case the precision is invalid. */ public Apfloat(double value, long precision, int radix) throws NumberFormatException, IllegalArgumentException, ApfloatRuntimeException { this(ApfloatHelper.createApfloat(value, precision, radix)); } /** * Reads an apfloat from a stream using default precision and radix. * The stream needs to be a PushbackReader, * as the first invalid character is pushed back to the stream.

* * Note that since only a pushback buffer of one character is used, * the number read may still not be valid. For example, if the stream * contains "-#" or "1.5e#" (here '#' * is the first invalid character), the number is actually not valid, and * only the character '#' would be put back to the stream.

* * The precision is determined similarly as in the {@link #Apfloat(String)} * constructor that is as the number of digits read from the stream. * * @param in The stream to read from * * @exception IOException If an I/O error occurs accessing the stream. * @exception NumberFormatException If the number is not valid. */ public Apfloat(PushbackReader in) throws IOException, NumberFormatException, ApfloatRuntimeException { this(ApfloatHelper.createApfloat(in, false)); } /** * Reads an apfloat from a stream using the specified precision. * The default radix is used. * * @param in The stream to read from * @param precision The precision of the number. * * @exception IOException If an I/O error occurs accessing the stream. * @exception NumberFormatException If the number is not valid. * @exception IllegalArgumentException In case the precision is invalid. * * @see #Apfloat(PushbackReader) */ public Apfloat(PushbackReader in, long precision) throws IOException, NumberFormatException, IllegalArgumentException, ApfloatRuntimeException { this(ApfloatHelper.createApfloat(in, precision, false)); } /** * Reads an apfloat from a stream using the specified precision * and radix. * * @param in The stream to read from * @param precision The precision of the number. * @param radix The radix of the number. * * @exception IOException If an I/O error occurs accessing the stream. * @exception NumberFormatException If the number is not valid. * @exception IllegalArgumentException In case the precision is invalid. * * @see #Apfloat(PushbackReader) */ public Apfloat(PushbackReader in, long precision, int radix) throws IOException, NumberFormatException, IllegalArgumentException, ApfloatRuntimeException { this(ApfloatHelper.createApfloat(in, precision, radix, false)); } /** * Constructs an apfloat from a BigInteger. * Precision will be {@link #INFINITE} and the default radix * is used. * * @param value The value of the number. * * @exception NumberFormatException If the default radix is not valid. */ public Apfloat(BigInteger value) throws NumberFormatException, ApfloatRuntimeException { this(ApfloatHelper.createApfloat(value)); } /** * Constructs an apfloat from a BigInteger with * the specified precision. The default radix is used. * * @param value The value of the number. * @param precision The precision of the number. * * @exception NumberFormatException If the default radix is not valid. * @exception IllegalArgumentException In case the precision is invalid. */ public Apfloat(BigInteger value, long precision) throws NumberFormatException, IllegalArgumentException, ApfloatRuntimeException { this(ApfloatHelper.createApfloat(value, precision)); } /** * Constructs an apfloat from a BigInteger with * the specified precision and radix. * * @param value The value of the number. * @param precision The precision of the number. * @param radix The radix of the number. * * @exception NumberFormatException If the radix is not valid. * @exception IllegalArgumentException In case the precision is invalid. */ public Apfloat(BigInteger value, long precision, int radix) throws NumberFormatException, IllegalArgumentException, ApfloatRuntimeException { this(ApfloatHelper.createApfloat(value, precision, radix)); } /** * Creates an apfloat from a BigDecimal. An apfloat created this * way will always have radix 10 regardless of the current default radix. * * @param value The value to use. */ public Apfloat(BigDecimal value) throws ApfloatRuntimeException { this(ApfloatHelper.createApfloat(value)); } /** * Creates an apfloat from a BigDecimal. An apfloat created this * way will always have radix 10 regardless of the current default radix. * * @param value The value to use. * @param precision The precision to use, in decimal digits. * * @exception IllegalArgumentException In case the precision is invalid. */ public Apfloat(BigDecimal value, long precision) throws IllegalArgumentException, ApfloatRuntimeException { this(ApfloatHelper.createApfloat(value, precision)); } /** * Radix of this apfloat. * * @return Radix of this apfloat. */ @Override public int radix() { return this.impl.radix(); } /** * Real part of this apfloat. * * @return this */ @Override public Apfloat real() { return this; } /** * Imaginary part of this apfloat. * * @return {@link #ZERO} */ @Override public Apfloat imag() { return Apfloat.ZEROS[radix()]; } /** * Returns the precision of this apfloat. * * @return The precision of this apfloat in number of digits of the radix in which it's presented. */ @Override public long precision() throws ApfloatRuntimeException { return this.impl.precision(); } /** * Returns an apfloat with the same value as this apfloat accurate to the * specified precision.

* * If the requested precision less than this number's current precision, the * functionality is quite obvious: the precision is simply truncated, and e.g. * comparison and equality checking will work as expected. Some rounding errors * in e.g. addition and subtraction may still occur, as "invisible" trailing * digits can remain in the number.

* * If the requested precision more than this number's current precision, the * functionality is quite undefined: the digits up to this number's current * precision are guaranteed to be the same, but the "new" digits are undefined: * they may be zero, or they may be digits that have been previously discarded * with a call to precision() with a smaller number of digits, or they may be * something else, or any combination of these.

* * These limitations allow various performance optimizations to be made. * * @param precision Precision of the new apfloat. * * @return An apfloat with the specified precision and same value as this apfloat. * * @exception IllegalArgumentException If precision is <= 0. */ @Override public Apfloat precision(long precision) throws IllegalArgumentException, ApfloatRuntimeException { ApfloatHelper.checkPrecision(precision); return new Apfloat(getImpl(precision)); } /** * Returns the scale of this apfloat. The scale is defined here as

* * apfloat = signum * mantissa * radixscale

* * where 1/radix <= mantissa < 1. In other words, * scale = floor(logradix(apfloat)) + 1.

* * For example, 1 has a scale of 1, and 100 has a scale of 3 (in radix 10). * For integers, scale is equal to the number of digits in the apfloat.

* * Zero has a scale of -INFINITE.

* * Note that this definition of scale is different than in java.math.BigDecimal. * * @return The exponent of this apfloat in number of digits of the radix in which it's presented. */ @Override public long scale() throws ApfloatRuntimeException { if (signum() == 0) { return -INFINITE; } else { return this.impl.scale(); } } /** * Returns the size of this apfloat. The size is defined here as

* * apfloat = signum * mantissa * radixscale and

* mantissa = n / radixsize

* * where 1/radix <= mantissa < 1 and n is the smallest possible integer. * In other words, the size is the number of significant digits in the * mantissa (excluding leading and trailing zeros but including all zeros * between the first and last nonzero digit). * * For example, 1 has a size of 1, and 100 has also a size of 1 (in radix 10). * 11 has a size of 2, and 10001000 has a size of 5.

* * Zero has a size of 0. * * @return The number of digits in this number, from the most significant digit to the least significant nonzero digit, in the radix in which it's presented. * * @since 1.6 */ @Override public long size() throws ApfloatRuntimeException { if (signum() == 0) { return 0; } else { return this.impl.size(); } } /** * Returns the signum function of this apfloat. * * @return -1, 0 or 1 as the value of this apfloat is negative, zero or positive, correspondingly. */ public int signum() { return this.impl.signum(); } /** * Returns if this number has an integer value. Note that this does not * necessarily mean that this object is an instance of {@link Apint}. * Neither does it mean that the precision is infinite. * * @return If this number's value is an integer. * * @since 1.9.0 */ @Override public boolean isInteger() throws ApfloatRuntimeException { return signum() == 0 || size() <= scale(); } /** * Returns if this apfloat is "short". In practice an apfloat is "short" if its * mantissa fits in one machine word. If the apfloat is "short", some algorithms * can be performed faster.

* * For example, division by a "short" apfloat requires only a single pass through * the data, but that algorithm can't be used for divisors that aren't "short", * where calculating an inverse root is required instead.

* * The return value of this method is implementation dependent. * * @return true if the apfloat is "short", false if not. */ public boolean isShort() throws ApfloatRuntimeException { return this.impl.isShort(); } /** * Negative value. * * @return -this. * * @since 1.1 */ @Override public Apfloat negate() throws ApfloatRuntimeException { return new Apfloat(this.impl.negate()); } /** * Adds two apfloats. * * @param x The number to be added to this number. * * @return this + x. */ public Apfloat add(Apfloat x) throws ApfloatRuntimeException { if (x.signum() == 0) { // x + 0 = x return this; } else if (signum() == 0) { // 0 + x = x return x; } return addOrSubtract(x, false); } /** * Subtracts two apfloats. * * @param x The number to be subtracted from this number. * * @return this - x. */ public Apfloat subtract(Apfloat x) throws ApfloatRuntimeException { if (x.signum() == 0) { // x - 0 = x return this; } else if (signum() == 0) { ApfloatImpl impl = x.getImpl(); impl = impl.negate(); return new Apfloat(impl); } return addOrSubtract(x, true); } private Apfloat addOrSubtract(Apfloat x, boolean subtract) throws ApfloatRuntimeException { long[] precisions = ApfloatHelper.getMatchingPrecisions(this, x); ApfloatImpl impl; if (precisions[0] == 0) { impl = x.getImpl(precisions[1]); if (subtract) { impl = impl.negate(); } } else if (precisions[1] == 0) { impl = getImpl(precisions[0]); } else { impl = getImpl(precisions[0]); ApfloatImpl xImpl = x.getImpl(precisions[1]); impl = impl.addOrSubtract(xImpl, subtract); } return new Apfloat(impl); } /** * Multiplies two apfloats. * * @param x The number to be multiplied by this number. * * @return this * x. */ public Apfloat multiply(Apfloat x) throws ApfloatRuntimeException { if (signum() == 0) { // 0 * x = 0 return this; } else if (x.signum() == 0) { // x * 0 = 0 return x; } else if (equals(ONE)) { // 1 * x = x return x.precision(Math.min(precision(), x.precision())); } else if (x.equals(ONE)) { // x * 1 = x return precision(Math.min(precision(), x.precision())); } long targetPrecision = Math.min(precision(), x.precision()); ApfloatImpl thisImpl = getImpl(targetPrecision), xImpl = x.getImpl(targetPrecision), impl = thisImpl.multiply(xImpl); return new Apfloat(impl); } /** * Divides two apfloats. * * @param x The number by which this number is to be divided. * * @return this / x. * * @exception ArithmeticException In case the divisor is zero. */ public Apfloat divide(Apfloat x) throws ArithmeticException, ApfloatRuntimeException { if (x.signum() == 0) { throw new ArithmeticException(signum() == 0 ? "Zero divided by zero" : "Division by zero"); } else if (signum() == 0) { // 0 / x = 0 return this; } else if (x.equals(ONE)) { // x / 1 = x return precision(Math.min(precision(), x.precision())); } long targetPrecision = Math.min(precision(), x.precision()); if (x.isShort()) { ApfloatImpl thisImpl = getImpl(targetPrecision), xImpl = x.getImpl(targetPrecision), impl = thisImpl.divideShort(xImpl); return new Apfloat(impl); } else { Apfloat inverse = ApfloatMath.inverseRoot(x, 1, targetPrecision); return multiply(inverse); } } /** * Calculates the remainder when divided by an apfloat. * The result has the same sign as this number. * If x is zero, then zero is returned. * * @param x The number that is used as the divisor in the remainder calculation. * * @return this % x. * * @see ApfloatMath#fmod(Apfloat,Apfloat) * * @since 1.2 */ public Apfloat mod(Apfloat x) throws ApfloatRuntimeException { return ApfloatMath.fmod(this, x); } /** * Floor function. Returns the largest (closest to positive infinity) value * that is not greater than this apfloat and is equal to a mathematical integer. * * @return This apfloat rounded towards negative infinity. */ public Apint floor() throws ApfloatRuntimeException { if (signum() >= 0) { return new Apint(new Apfloat(this.impl.absFloor())); } else { return new Apint(new Apfloat(this.impl.absCeil())); } } /** * Ceiling function. Returns the smallest (closest to negative infinity) value * that is not less than this apfloat and is equal to a mathematical integer. * * @return This apfloat rounded towards positive infinity. */ public Apint ceil() throws ApfloatRuntimeException { if (signum() >= 0) { return new Apint(new Apfloat(this.impl.absCeil())); } else { return new Apint(new Apfloat(this.impl.absFloor())); } } /** * Truncates fractional part. * * @return This apfloat rounded towards zero. */ public Apint truncate() throws ApfloatRuntimeException { return new Apint(new Apfloat(this.impl.absFloor())); } /** * Returns the fractional part. The fractional part is always 0 <= abs(frac()) < 1. * The fractional part has the same sign as the number. For the fractional and integer parts, this always holds:

* * x = x.truncate() + x.frac() * * @return The fractional part of this apfloat. * * @since 1.7.0 */ public Apfloat frac() throws ApfloatRuntimeException { return new Apfloat(this.impl.frac()); } /** * Returns the value of the this number as a double. * If the number is too big to fit in a double, * Double.POSITIVE_INFINITY or * Double.NEGATIVE_INFINITY is returned. * * @return The numeric value represented by this object after conversion to type double. */ @Override public double doubleValue() { int targetPrecision = ApfloatHelper.getDoublePrecision(radix()); ApfloatImpl impl = getImpl(targetPrecision); return impl.doubleValue(); } /** * Returns the value of the this number as a float. * If the number is too big to fit in a float, * Float.POSITIVE_INFINITY or * Float.NEGATIVE_INFINITY is returned. * * @return The numeric value represented by this object after conversion to type float. */ @Override public float floatValue() { return (float) doubleValue(); } /** * Returns the value of the this number as a byte. * If the number is too big to fit in a byte, * Byte.MIN_VALUE or * Byte.MAX_VALUE is returned. * * @return The numeric value represented by this object after conversion to type byte. */ @Override public byte byteValue() { long longValue = longValue(); return (byte) Math.min(Math.max(longValue, Byte.MIN_VALUE), Byte.MAX_VALUE); } /** * Returns the value of the this number as a short. * If the number is too big to fit in a short, * Short.MIN_VALUE or * Short.MAX_VALUE is returned. * * @return The numeric value represented by this object after conversion to type short. */ @Override public short shortValue() { long longValue = longValue(); return (short) Math.min(Math.max(longValue, Short.MIN_VALUE), Short.MAX_VALUE); } /** * Returns the value of the this number as an int. * If the number is too big to fit in an int, * Integer.MIN_VALUE or * Integer.MAX_VALUE is returned. * * @return The numeric value represented by this object after conversion to type int. */ @Override public int intValue() { long longValue = longValue(); return (int) Math.min(Math.max(longValue, Integer.MIN_VALUE), Integer.MAX_VALUE); } /** * Returns the value of the this number as a long. * If the number is too big to fit in a long, * Long.MIN_VALUE or * Long.MAX_VALUE is returned. * * @return The numeric value represented by this object after conversion to type long. */ @Override public long longValue() { int targetPrecision = ApfloatHelper.getLongPrecision(radix()); ApfloatImpl impl = getImpl(targetPrecision); return impl.longValue(); } @Override public long longValueExact() throws ArithmeticException { if (!isInteger()) { throw new ArithmeticException("Rounding necessary"); } long value = longValue(); if (!new Apint(value, radix()).equals(truncate())) { throw new ArithmeticException("Out of range"); } return value; } /** * Computes number of equal digits.

* * Compares the digits of the numbers starting from the * most significant digits. The exponent and sign are * taken into consideration, so if either one doesn't match, * the numbers are considered to have zero equal digits.

* * For example, the numbers 12345 and 123456 have zero * matching digits, and the numbers 12345 and 12355 have * three matching digits.

* * The result of this method is roughly equal to * Math.min(scale(), x.scale()) - subtract(x).scale() * but it typically is a lot more efficient to execute. * * @param x Number to compare with. * * @return Number of matching digits in the radix in which the numbers are presented. */ public long equalDigits(Apfloat x) throws ApfloatRuntimeException { long targetPrecision = Math.min(precision(), x.precision()); ApfloatImpl thisImpl = getImpl(targetPrecision), xImpl = x.getImpl(targetPrecision); return thisImpl.equalDigits(xImpl); } /** * Convert this apfloat to the specified radix. * * @param radix The radix. * * @exception NumberFormatException If the radix is invalid. * * @since 1.2 */ @Override public Apfloat toRadix(int radix) throws NumberFormatException, ApfloatRuntimeException { return RadixConversionHelper.toRadix(this, radix); } /** * Compare this apfloat to the specified apfloat.

* * Note: if two apfloats are compared where one number doesn't have enough * precise digits, the mantissa is assumed to contain zeros. For example: * *

     * Apfloat x = new Apfloat("0.12", 2);
     * Apfloat y = new Apfloat("0.12345", 5);
     * 
* * Now x.compareTo(y) < 0 because x is assumed to * be 0.12000.

* * However, new Apfloat("0.12", 2) and new Apfloat("0.12", 5) * would be considered equal. * * @param x Apfloat to which this apfloat is to be compared. * * @return -1, 0 or 1 as this apfloat is numerically less than, equal to, or greater than x. */ @Override public int compareTo(Apfloat x) { if (x.preferCompare(this)) { // Special handling of aprationals return -x.compareTo(this); } else { // Compare with maximum available precision; would not be efficient with aprationals return getImpl().compareTo(x.getImpl()); } } /** * Tests if the comparison with equals and compareTo should be done in the opposite order.

* * Implementations should avoid infinite recursion. * * @param x The number to compare to. * * @return true if this object should invoke x.equals(this) and -x.compareTo(this) instead of comparing normally. * * @since 1.7.0 */ public boolean preferCompare(Apfloat x) { return false; } /** * Compares this object to the specified object.

* * Note: if two apfloats are compared where one number doesn't have enough * precise digits, the mantissa is assumed to contain zeros. * See {@link #compareTo(Apfloat)}. * * @param obj The object to compare with. * * @return true if the objects are equal; false otherwise. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } else if (obj instanceof Apfloat) { Apfloat x = (Apfloat) obj; if (x.preferCompare(this)) { // Special handling of aprationals return x.equals(this); } return getImpl().equals(x.getImpl()); } else { return super.equals(obj); } } /** * Tests two apfloat numbers for equality. * Returns false if the numbers are definitely known to be not equal. * If true is returned, equality is unknown and should be verified by * calling {@link #equals(Object)}. * This method is usually significantly faster than calling equals(Object). * * @param x The number to test against. * * @return false if the numbers are definitely not equal, true if unknown. * * @since 1.10.0 */ public boolean test(Apfloat x) throws ApfloatRuntimeException { if (x.preferCompare(this)) { // Special handling of aprationals return x.test(this); } else { return signum() == x.signum() && scale() == x.scale() && size() == x.size(); } } /** * Returns a hash code for this apfloat. * * @return The hash code value for this object. */ @Override public int hashCode() { return this.impl.hashCode(); } /** * Returns a string representation of this apfloat. * * @param pretty true to use a fixed-point notation, false to use an exponential notation. * * @return A string representing this object. */ @Override public String toString(boolean pretty) throws ApfloatRuntimeException { return this.impl.toString(pretty); } /** * Write a string representation of this apfloat to a Writer. * * @param out The output Writer. * @param pretty true to use a fixed-point notation, false to use an exponential notation. * * @exception IOException In case of I/O error writing to the stream. */ @Override public void writeTo(Writer out, boolean pretty) throws IOException, ApfloatRuntimeException { this.impl.writeTo(out, pretty); } /** * Formats the object using the provided formatter.

* * The format specifiers affect the output as follows: *

    *
  • By default, the exponential notation is used.
  • *
  • If the alternate format is specified ('#'), then the fixed-point notation is used.
  • *
  • Width is the minimum number of characters output. Any padding is done using spaces. Padding is on the left by default.
  • *
  • If the '-' flag is specified, then the padding will be on the right.
  • *
  • The precision is the number of significant digts output. If the precision of the number exceeds the number of characters output, the rounding mode for output is undefined.
  • *
*

* * The decimal separator will be localized if the formatter specifies a locale. * The digits will be localized also, but only if the radix is less than or equal to 10. * * @param formatter The formatter. * @param flags The flags to modify the output format. * @param width The minimum number of characters to be written to the output, or -1 for no minimum. * @param precision The maximum number of characters to be written to the output, or -1 for no maximum. * * @since 1.3 */ @Override public void formatTo(Formatter formatter, int flags, int width, int precision) { Apfloat x = (precision == -1 ? this : ApfloatHelper.limitPrecision(this, precision)); try { Writer out = FormattingHelper.wrapAppendableWriter(formatter.out()); out = FormattingHelper.wrapLocalizeWriter(out, formatter, radix(), (flags & UPPERCASE) == UPPERCASE); if (width == -1) { x.writeTo(out, (flags & ALTERNATE) == ALTERNATE); } else { out = FormattingHelper.wrapPadWriter(out, (flags & LEFT_JUSTIFY) == LEFT_JUSTIFY); x.writeTo(out, (flags & ALTERNATE) == ALTERNATE); FormattingHelper.finishPad(out, width); } } catch (IOException ioe) { // Ignore as we can't propagate it; unfortunately we can't set it to the formattable either } } /** * Returns an ApfloatImpl representing the actual instance * of this apfloat up to the requested precision.

* * For apfloats this is simply the underlying ApfloatImpl, * but e.g. the {@link Aprational} class implements this so that * it only returns an approximation of the rational number. * * @param precision Precision of the ApfloatImpl that is needed. * * @return An ApfloatImpl representing this object to the requested precision. */ protected ApfloatImpl getImpl(long precision) throws ApfloatRuntimeException { if (precision == precision()) { return this.impl; } else { return this.impl.precision(precision); } } // Round away from zero i.e. opposite direction of rounding than in truncate() Apint roundAway() throws ApfloatRuntimeException { return new Apint(new Apfloat(this.impl.absCeil())); } Apfloat scale(long scale) { return ApfloatMath.scale(this, scale); } Apfloat abs() { return ApfloatMath.abs(this); } int compareToHalf() { return RoundingHelper.compareToHalf(this); } private ApfloatImpl getImpl() throws ApfloatRuntimeException { long precision = precision(); return getImpl(precision); } private static final long serialVersionUID = -36707433458144439L; private ApfloatImpl impl; }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy