Bugzilla 55043 and 55042: initial support for Complex and Quotient functions
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1488734 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
0dfb528355
commit
4d81d34d5d
119
src/java/org/apache/poi/ss/formula/functions/Complex.java
Normal file
119
src/java/org/apache/poi/ss/formula/functions/Complex.java
Normal file
@ -0,0 +1,119 @@
|
||||
package org.apache.poi.ss.formula.functions;
|
||||
|
||||
import org.apache.poi.ss.formula.eval.*;
|
||||
|
||||
/**
|
||||
* Implementation for Excel COMPLEX () function.<p/>
|
||||
* <p/>
|
||||
* <b>Syntax</b>:<br/> <b>COMPLEX </b>(<b>real_num</b>,<b>i_num</b>,<b>suffix </b> )<br/>
|
||||
* <p/>
|
||||
* Converts real and imaginary coefficients into a complex number of the form x + yi or x + yj.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* All complex number functions accept "i" and "j" for suffix, but neither "I" nor "J".
|
||||
* Using uppercase results in the #VALUE! error value. All functions that accept two
|
||||
* or more complex numbers require that all suffixes match.
|
||||
* <p/>
|
||||
* <b>real_num</b> The real coefficient of the complex number.
|
||||
* If this argument is nonnumeric, this function returns the #VALUE! error value.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* <b>i_num</b> The imaginary coefficient of the complex number.
|
||||
* If this argument is nonnumeric, this function returns the #VALUE! error value.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* <b>suffix</b> The suffix for the imaginary component of the complex number.
|
||||
* <ul>
|
||||
* <li>If omitted, suffix is assumed to be "i".</li>
|
||||
* <li>If suffix is neither "i" nor "j", COMPLEX returns the #VALUE! error value.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author cedric dot walter @ gmail dot com
|
||||
*/
|
||||
public class Complex extends Var2or3ArgFunction {
|
||||
|
||||
public static final String DEFAULT_SUFFIX = "i";
|
||||
public static final String SUPPORTED_SUFFIX = "j";
|
||||
|
||||
@Override
|
||||
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval real_num, ValueEval i_num) {
|
||||
return this.evaluate(srcRowIndex, srcColumnIndex, real_num, i_num, new StringEval(DEFAULT_SUFFIX));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval real_num, ValueEval i_num, ValueEval suffix) {
|
||||
ValueEval veText1;
|
||||
try {
|
||||
veText1 = OperandResolver.getSingleValue(real_num, srcRowIndex, srcColumnIndex);
|
||||
} catch (EvaluationException e) {
|
||||
return e.getErrorEval();
|
||||
}
|
||||
double realNum = 0;
|
||||
try {
|
||||
realNum = OperandResolver.coerceValueToDouble(veText1);
|
||||
} catch (EvaluationException e) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
|
||||
ValueEval veINum;
|
||||
try {
|
||||
veINum = OperandResolver.getSingleValue(i_num, srcRowIndex, srcColumnIndex);
|
||||
} catch (EvaluationException e) {
|
||||
return e.getErrorEval();
|
||||
}
|
||||
double realINum = 0;
|
||||
try {
|
||||
realINum = OperandResolver.coerceValueToDouble(veINum);
|
||||
} catch (EvaluationException e) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
|
||||
String suffixValue = OperandResolver.coerceValueToString(suffix);
|
||||
if (suffixValue.isEmpty()) {
|
||||
suffixValue = DEFAULT_SUFFIX;
|
||||
}
|
||||
if (suffixValue.equals(DEFAULT_SUFFIX.toUpperCase()) || suffixValue.equals(SUPPORTED_SUFFIX.toUpperCase())) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
if (!(suffixValue.equals(DEFAULT_SUFFIX) || suffixValue.equals(SUPPORTED_SUFFIX))) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
|
||||
StringBuffer strb = new StringBuffer("");
|
||||
if (realNum != 0) {
|
||||
if (isDoubleAnInt(realNum)) {
|
||||
strb.append(new Double(realNum).intValue());
|
||||
} else {
|
||||
strb.append(realNum);
|
||||
}
|
||||
}
|
||||
if (realINum != 0) {
|
||||
if (strb.length() != 0) {
|
||||
if (realINum > 0) {
|
||||
strb.append("+");
|
||||
}
|
||||
}
|
||||
|
||||
if (realINum != 1 && realINum != -1) {
|
||||
if (isDoubleAnInt(realINum)) {
|
||||
strb.append(new Double(realINum).intValue());
|
||||
} else {
|
||||
strb.append(realINum);
|
||||
}
|
||||
}
|
||||
|
||||
strb.append(suffixValue);
|
||||
}
|
||||
|
||||
return new StringEval(strb.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param number
|
||||
* @return
|
||||
*/
|
||||
private boolean isDoubleAnInt(double number) {
|
||||
return (number == Math.floor(number)) && !Double.isInfinite(number);
|
||||
}
|
||||
|
||||
}
|
49
src/java/org/apache/poi/ss/formula/functions/Quotient.java
Normal file
49
src/java/org/apache/poi/ss/formula/functions/Quotient.java
Normal file
@ -0,0 +1,49 @@
|
||||
package org.apache.poi.ss.formula.functions;
|
||||
|
||||
import org.apache.poi.ss.formula.eval.ValueEval;
|
||||
|
||||
|
||||
import org.apache.poi.ss.formula.eval.*;
|
||||
|
||||
/**
|
||||
* <p>Implementation for Excel QUOTIENT () function.<p/>
|
||||
* <p>
|
||||
* <b>Syntax</b>:<br/> <b>QUOTIENT</b>(<b>Numerator</b>,<b>Denominator</b>)<br/>
|
||||
* <p/>
|
||||
* <p>
|
||||
* Numerator is the dividend.
|
||||
* Denominator is the divisor.
|
||||
*
|
||||
* Returns the integer portion of a division. Use this function when you want to discard the remainder of a division.
|
||||
* <p/>
|
||||
*
|
||||
* If either enumerator/denominator is non numeric, QUOTIENT returns the #VALUE! error value.
|
||||
* If denominator is equals to zero, QUOTIENT returns the #DIV/0! error value.
|
||||
*
|
||||
* @author cedric dot walter @ gmail dot com
|
||||
*/
|
||||
public class Quotient extends Fixed2ArgFunction {
|
||||
@Override
|
||||
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval venumerator, ValueEval vedenominator) {
|
||||
|
||||
double enumerator = 0;
|
||||
try {
|
||||
enumerator = OperandResolver.coerceValueToDouble(venumerator);
|
||||
} catch (EvaluationException e) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
|
||||
double denominator = 0;
|
||||
try {
|
||||
denominator = OperandResolver.coerceValueToDouble(vedenominator);
|
||||
} catch (EvaluationException e) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
|
||||
if (denominator == 0) {
|
||||
return ErrorEval.DIV_ZERO;
|
||||
}
|
||||
|
||||
return new StringEval(String.valueOf((int)(enumerator / denominator)));
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.ss.formula.functions;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.poi.ss.formula.eval.ErrorEval;
|
||||
import org.apache.poi.ss.formula.eval.StringEval;
|
||||
import org.apache.poi.ss.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* Tests for {@link Complex}
|
||||
*
|
||||
* @author cedric dot walter @ gmail dot com
|
||||
*/
|
||||
public class TestComplex extends TestCase
|
||||
{
|
||||
private static ValueEval invokeValue(String real_num, String i_num, String suffix) {
|
||||
ValueEval[] args = new ValueEval[]{new StringEval(real_num), new StringEval(i_num), new StringEval(suffix)};
|
||||
return new Complex().evaluate(args, -1, -1);
|
||||
}
|
||||
|
||||
private static void confirmValue(String msg, String real_num, String i_num, String suffix, String expected) {
|
||||
ValueEval result = invokeValue(real_num, i_num, suffix);
|
||||
assertEquals(StringEval.class, result.getClass());
|
||||
assertEquals(msg, expected, ((StringEval) result).getStringValue());
|
||||
}
|
||||
|
||||
private static void confirmValueError(String msg, String real_num, String i_num, String suffix, ErrorEval numError) {
|
||||
ValueEval result = invokeValue(real_num, i_num, suffix);
|
||||
assertEquals(ErrorEval.class, result.getClass());
|
||||
assertEquals(msg, numError, result);
|
||||
}
|
||||
|
||||
public void testBasic() {
|
||||
confirmValue("Complex number with 3 and 4 as the real and imaginary coefficients (3 + 4i)", "3","4", "", "3+4i");
|
||||
confirmValue("Complex number with 3 and 4 as the real and imaginary coefficients, and j as the suffix (3 + 4j)", "3","4", "j", "3+4j");
|
||||
|
||||
confirmValue("Complex number with 0 and 1 as the real and imaginary coefficients (i)", "0","1", "", "i");
|
||||
confirmValue("Complex number with 1 and 0 as the real and imaginary coefficients (1)", "1","0", "", "1");
|
||||
|
||||
confirmValue("Complex number with 2 and 3 as the real and imaginary coefficients (2 + 3i)", "2","3", "", "2+3i");
|
||||
confirmValue("Complex number with -2 and -3 as the real and imaginary coefficients (-2-3i)", "-2","-3", "", "-2-3i");
|
||||
|
||||
confirmValue("Complex number with -2 and -3 as the real and imaginary coefficients (-0.5-3.2i)", "-0.5","-3.2", "", "-0.5-3.2i");
|
||||
}
|
||||
|
||||
public void testErrors() {
|
||||
confirmValueError("argument is nonnumeric", "ABCD", "","", ErrorEval.VALUE_INVALID);
|
||||
confirmValueError("argument is nonnumeric", "1", "ABCD","", ErrorEval.VALUE_INVALID);
|
||||
confirmValueError("f suffix is neither \"i\" nor \"j\"", "1", "1","k", ErrorEval.VALUE_INVALID);
|
||||
|
||||
confirmValueError("never use \"I\" ", "1", "1","I", ErrorEval.VALUE_INVALID);
|
||||
confirmValueError("never use \"J\" ", "1", "1","J", ErrorEval.VALUE_INVALID);
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.ss.formula.functions;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.poi.ss.formula.eval.ErrorEval;
|
||||
import org.apache.poi.ss.formula.eval.StringEval;
|
||||
import org.apache.poi.ss.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* Tests for {@link Quotient}
|
||||
*
|
||||
* @author cedric dot walter @ gmail dot com
|
||||
*/
|
||||
public class TestQuotient extends TestCase {
|
||||
private static ValueEval invokeValue(String numerator, String denominator) {
|
||||
ValueEval[] args = new ValueEval[]{new StringEval(numerator), new StringEval(denominator)};
|
||||
return new Quotient().evaluate(args, -1, -1);
|
||||
}
|
||||
|
||||
private static void confirmValue(String msg, String numerator, String denominator, String expected) {
|
||||
ValueEval result = invokeValue(numerator, denominator);
|
||||
assertEquals(StringEval.class, result.getClass());
|
||||
assertEquals(msg, expected, ((StringEval) result).getStringValue());
|
||||
}
|
||||
|
||||
private static void confirmValueError(String msg, String numerator, String denominator, ErrorEval numError) {
|
||||
ValueEval result = invokeValue(numerator, denominator);
|
||||
assertEquals(ErrorEval.class, result.getClass());
|
||||
assertEquals(msg, numError, result);
|
||||
}
|
||||
|
||||
public void testBasic() {
|
||||
confirmValue("Integer portion of 5/2 (2)", "5", "2", "2");
|
||||
confirmValue("Integer portion of 4.5/3.1 (1)", "4.5", "3.1", "1");
|
||||
|
||||
confirmValue("Integer portion of -10/3 (-3)", "-10", "3", "-3");
|
||||
confirmValue("Integer portion of -5.5/2 (-2)", "-5.5", "2", "-2");
|
||||
|
||||
confirmValue("Integer portion of Pi/Avogadro (0)", "3.14159", "6.02214179E+23", "0");
|
||||
}
|
||||
|
||||
public void testErrors() {
|
||||
confirmValueError("numerator is nonnumeric", "ABCD", "", ErrorEval.VALUE_INVALID);
|
||||
confirmValueError("denominator is nonnumeric", "", "ABCD", ErrorEval.VALUE_INVALID);
|
||||
|
||||
confirmValueError("denominator is nonnumeric", "3.14159", "0", ErrorEval.DIV_ZERO);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user