mirror of
				https://github.com/DanilaFe/abacus
				synced 2025-11-03 18:33:41 -08:00 
			
		
		
		
	Rewrite precise number to limit significant figures rather than decimal places. Add getMaxError to NumberInterface; modify numbers and StandardPlugin appropriately.
This commit is contained in:
		
							parent
							
								
									7ae59afade
								
							
						
					
					
						commit
						7b7f9936e4
					
				@ -128,5 +128,9 @@ public class NaiveNumber extends NumberInterface {
 | 
			
		||||
        return Double.toString(Math.round(value * shiftBy) / shiftBy);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public NumberInterface getMaxError(){
 | 
			
		||||
        return new NaiveNumber(Math.pow(10, -18));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -255,4 +255,11 @@ public abstract class NumberInterface {
 | 
			
		||||
        return promoteToInternal(toClass);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the smallest error this instance can tolerate depending
 | 
			
		||||
     * on its precision and value.
 | 
			
		||||
     * @return the smallest error that should be permitted in calculations.
 | 
			
		||||
     */
 | 
			
		||||
    public abstract NumberInterface getMaxError();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
package org.nwapw.abacus.number;
 | 
			
		||||
 | 
			
		||||
import java.math.BigDecimal;
 | 
			
		||||
import java.math.RoundingMode;
 | 
			
		||||
import java.math.MathContext;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A number that uses a BigDecimal to store its value,
 | 
			
		||||
@ -22,6 +22,21 @@ public class PreciseNumber extends NumberInterface {
 | 
			
		||||
     */
 | 
			
		||||
    public static final PreciseNumber TEN = new PreciseNumber(BigDecimal.TEN);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The number of extra significant figures kept in calculations before rounding for output.
 | 
			
		||||
     */
 | 
			
		||||
    private static int numExtraInternalSigFigs = 15;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * MathContext that is used when rounding a number prior to output.
 | 
			
		||||
     */
 | 
			
		||||
    private static MathContext outputContext = new MathContext(30);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * MathContext that is actually used in calculations.
 | 
			
		||||
     */
 | 
			
		||||
    private static MathContext internalContext = new MathContext(outputContext.getPrecision()+numExtraInternalSigFigs);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The value of the PreciseNumber.
 | 
			
		||||
     */
 | 
			
		||||
@ -48,7 +63,7 @@ public class PreciseNumber extends NumberInterface {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int getMaxPrecision() {
 | 
			
		||||
        return 65;
 | 
			
		||||
        return internalContext.getPrecision();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@ -58,7 +73,7 @@ public class PreciseNumber extends NumberInterface {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public NumberInterface divideInternal(NumberInterface divisor) {
 | 
			
		||||
        return new PreciseNumber(value.divide(((PreciseNumber) divisor).value, this.getMaxPrecision(), RoundingMode.HALF_UP));
 | 
			
		||||
        return new PreciseNumber(value.divide(((PreciseNumber) divisor).value, internalContext));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@ -147,7 +162,11 @@ public class PreciseNumber extends NumberInterface {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String toString() {
 | 
			
		||||
        BigDecimal rounded = value.setScale(getMaxPrecision() - 15, RoundingMode.HALF_UP);
 | 
			
		||||
        return rounded.stripTrailingZeros().toPlainString();
 | 
			
		||||
        return value.round(outputContext).toString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public NumberInterface getMaxError(){
 | 
			
		||||
        return new PreciseNumber(value.ulp()).multiplyInternal(TEN.intPowInternal(value.precision()-internalContext.getPrecision()));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -188,7 +188,7 @@ public class StandardPlugin extends Plugin {
 | 
			
		||||
         */
 | 
			
		||||
        private NumberInterface getLogPartialSum(NumberInterface x) {
 | 
			
		||||
 | 
			
		||||
            NumberInterface maxError = getMaxError(x);
 | 
			
		||||
            NumberInterface maxError = x.getMaxError();
 | 
			
		||||
            x = x.subtract(NaiveNumber.ONE.promoteTo(x.getClass())); //Terms used are for log(x+1).
 | 
			
		||||
            NumberInterface currentNumerator = x, currentTerm = x, sum = x;
 | 
			
		||||
            int n = 1;
 | 
			
		||||
@ -207,7 +207,7 @@ public class StandardPlugin extends Plugin {
 | 
			
		||||
         * @return the value of log(2) with the appropriate precision.
 | 
			
		||||
         */
 | 
			
		||||
        private NumberInterface getLog2(NumberInterface number) {
 | 
			
		||||
            NumberInterface maxError = getMaxError(number);
 | 
			
		||||
            NumberInterface maxError = number.getMaxError();
 | 
			
		||||
            //NumberInterface errorBound = fromInt(number.getClass(), 1);
 | 
			
		||||
            //We'll use the series \sigma_{n >= 1) ((1/3^n + 1/4^n) * 1/n)
 | 
			
		||||
            //In the following, a=1/3^n, b=1/4^n, c = 1/n.
 | 
			
		||||
@ -301,7 +301,7 @@ public class StandardPlugin extends Plugin {
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        protected NumberInterface applyInternal(NumberInterface[] params) {
 | 
			
		||||
            NumberInterface maxError = getMaxError(params[0]);
 | 
			
		||||
            NumberInterface maxError = params[0].getMaxError();
 | 
			
		||||
            int n = 0;
 | 
			
		||||
            if (params[0].signum() <= 0) {
 | 
			
		||||
                NumberInterface currentTerm = NaiveNumber.ONE.promoteTo(params[0].getClass()), sum = currentTerm;
 | 
			
		||||
@ -352,7 +352,7 @@ public class StandardPlugin extends Plugin {
 | 
			
		||||
                return NaiveNumber.ONE.promoteTo(params[1].getClass());
 | 
			
		||||
            //Detect integer bases:
 | 
			
		||||
            if(params[0].fractionalPart().compareTo(fromInt(params[0].getClass(), 0)) == 0
 | 
			
		||||
                    && FUNCTION_ABS.apply(params[0]).compareTo(fromInt(params[0].getClass(), Integer.MAX_VALUE)) < 0
 | 
			
		||||
                    && FUNCTION_ABS.apply(params[1]).compareTo(fromInt(params[0].getClass(), Integer.MAX_VALUE)) < 0
 | 
			
		||||
                    && FUNCTION_ABS.apply(params[1]).compareTo(fromInt(params[1].getClass(), 1)) >= 0){
 | 
			
		||||
                NumberInterface[] newParams = {params[0], params[1].fractionalPart()};
 | 
			
		||||
                return params[0].intPow(params[1].floor().intValue()).multiply(applyInternal(newParams));
 | 
			
		||||
@ -476,16 +476,6 @@ public class StandardPlugin extends Plugin {
 | 
			
		||||
        return sum;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the maximum error based on the precision of the class of number.
 | 
			
		||||
     *
 | 
			
		||||
     * @param number Any instance of the NumberInterface in question (should return an appropriate precision).
 | 
			
		||||
     * @return the maximum error.
 | 
			
		||||
     */
 | 
			
		||||
    private static NumberInterface getMaxError(NumberInterface number) {
 | 
			
		||||
        return fromInt(number.getClass(), 10).intPow(-number.getMaxPrecision());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * A factorial function that uses memoization for each number class; it efficiently
 | 
			
		||||
     * computes factorials of non-negative integers.
 | 
			
		||||
@ -517,7 +507,7 @@ public class StandardPlugin extends Plugin {
 | 
			
		||||
     */
 | 
			
		||||
    private static NumberInterface sinTaylor(NumberInterface x) {
 | 
			
		||||
        NumberInterface power = x, multiplier = x.multiply(x).negate(), currentTerm = x, sum = x;
 | 
			
		||||
        NumberInterface maxError = getMaxError(x);
 | 
			
		||||
        NumberInterface maxError = x.getMaxError();
 | 
			
		||||
        int n = 1;
 | 
			
		||||
        do {
 | 
			
		||||
            n += 2;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user