diff --git a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/FinanceFunction.java b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/FinanceFunction.java new file mode 100644 index 000000000..2df75d949 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/FinanceFunction.java @@ -0,0 +1,62 @@ +/* + * Created on Jun 20, 2005 + * + */ +package org.apache.poi.hssf.record.formula.functions; + +import org.apache.poi.hssf.record.formula.eval.BoolEval; +import org.apache.poi.hssf.record.formula.eval.ErrorEval; +import org.apache.poi.hssf.record.formula.eval.Eval; +import org.apache.poi.hssf.record.formula.eval.NumericValueEval; +import org.apache.poi.hssf.record.formula.eval.ValueEval; +import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator; + + +/** + * @author Amol S. Deshmukh < amolweb at ya hoo dot com > + * Super class for all Evals for financial function evaluation. + * + */ +public abstract class FinanceFunction extends NumericFunction { + private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR = + new ValueEvalToNumericXlator((short) (0 + | ValueEvalToNumericXlator.BOOL_IS_PARSED + | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED + | ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED + | ValueEvalToNumericXlator.STRING_IS_PARSED + | ValueEvalToNumericXlator.REF_STRING_IS_PARSED + | ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED + | ValueEvalToNumericXlator.BLANK_IS_PARSED + | ValueEvalToNumericXlator.REF_BLANK_IS_PARSED + | ValueEvalToNumericXlator.EVALUATED_REF_BLANK_IS_PARSED + //| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED + //| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE + //| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE + )); + + /** + * this is the default impl of the factory(ish) method getXlator. + * Subclasses can override this method + * if they desire to return a different ValueEvalToNumericXlator instance + * than the default. + */ + protected ValueEvalToNumericXlator getXlator() { + return DEFAULT_NUM_XLATOR; + } + + protected ValueEval singleOperandNumericAsBoolean(Eval eval, int srcRow, short srcCol) { + ValueEval retval = null; + retval = singleOperandEvaluate(eval, srcRow, srcCol); + if (retval instanceof NumericValueEval) { + NumericValueEval nve = (NumericValueEval) retval; + retval = (nve.getNumberValue() == 0) + ? BoolEval.FALSE + : BoolEval.TRUE; + } + else { + retval = ErrorEval.VALUE_INVALID; + } + return retval; + } + +} diff --git a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/FinanceLib.java b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/FinanceLib.java index 90378c808..d53067aa1 100644 --- a/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/FinanceLib.java +++ b/src/scratchpad/src/org/apache/poi/hssf/record/formula/functions/FinanceLib.java @@ -24,9 +24,26 @@ package org.apache.poi.hssf.record.formula.functions; *
    *
  1. GNU Emacs Calc 2.02 Manual: http://theory.uwinnipeg.ca/gnu/calc/calc_203.html
  2. *
  3. Yahoo Financial Glossary: http://biz.yahoo.com/f/g/nn.html#y
  4. + *
  5. MS Excel function reference: http://office.microsoft.com/en-us/assistance/CH062528251033.aspx
  6. *
+ *

Implementation Notes:

+ * Symbols used in the formulae that follow:
+ * + * [From MS Excel function reference] Following are some of the key formulas + * that are used in this implementation: + *
+ * p(1+r)^n + y(1+rt)((1+r)^n-1)/r + f=0   ...{when r!=0}
+ * ny + p + f=0                            ...{when r=0}
+ * 
*/ -public class FinanceLib { +public final class FinanceLib { // constants for default values @@ -46,11 +63,18 @@ public class FinanceLib { * @param t type (true=pmt at end of period, false=pmt at begining of period) * @return */ - public static double fv(double r, int n, double y, double p, boolean t) { - double r1 = r + 1; - return ((1-Math.pow(r1, n)) * (t ? r1 : 1) * y ) / r - - - p*Math.pow(r1, n); + public static double fv(double r, double n, double y, double p, boolean t) { + double retval = 0; + if (r == 0) { + retval = -1*(p+(n*y)); + } + else { + double r1 = r + 1; + retval =((1-Math.pow(r1, n)) * (t ? r1 : 1) * y ) / r + - + p*Math.pow(r1, n); + } + return retval; } /** @@ -65,11 +89,18 @@ public class FinanceLib { * @param t * @return */ - public static double pv(double r, int n, double y, double f, boolean t) { - double r1 = r + 1; - return (( ( 1 - Math.pow(r1, n) ) / r ) * (t ? r1 : 1) * y - f) - / - Math.pow(r1, n); + public static double pv(double r, double n, double y, double f, boolean t) { + double retval = 0; + if (r == 0) { + retval = -1*((n*y)+f); + } + else { + double r1 = r + 1; + retval =(( ( 1 - Math.pow(r1, n) ) / r ) * (t ? r1 : 1) * y - f) + / + Math.pow(r1, n); + } + return retval; } /** @@ -102,13 +133,20 @@ public class FinanceLib { * @param t * @return */ - public static double pmt(double r, int n, double p, double f, boolean t) { + public static double pmt(double r, double n, double p, double f, boolean t) { + double retval = 0; + if (r == 0) { + retval = -1*(f+p)/n; + } + else { double r1 = r + 1; - return ( f + p * Math.pow(r1, n) ) * r + retval = ( f + p * Math.pow(r1, n) ) * r / ((t ? r1 : 1) * (1 - Math.pow(r1, n))); + } + return retval; } - + /** * * @param r @@ -118,15 +156,23 @@ public class FinanceLib { * @param t * @return */ - public static int nper(double r, double y, double p, double f, boolean t) { - double r1 = r + 1; - double ryr = (t ? r1 : 1) * y / r; - double a1 = ((ryr-f) < 0) ? Math.log(f-ryr) : Math.log(ryr-f); - double a2 = ((ryr-f) < 0) ? Math.log(-p-ryr) : Math.log(p+ryr); - double a3 = Math.log(r1); - double dval = ( a1 - a2 ) / a3; - - return (int) Math.round(dval); + public static double nper(double r, double y, double p, double f, boolean t) { + double retval = 0; + if (r == 0) { + retval = -1 * (f + p) / y; + } else { + double r1 = r + 1; + double ryr = (t ? r1 : 1) * y / r; + double a1 = ((ryr - f) < 0) + ? Math.log(f - ryr) + : Math.log(ryr - f); + double a2 = ((ryr - f) < 0) + ? Math.log(-p - ryr) + : Math.log(p + ryr); + double a3 = Math.log(r1); + retval = (a1 - a2) / a3; + } + return retval; }