Add remainder function
This commit is contained in:
parent
6a4d19517e
commit
735f1d584a
|
@ -0,0 +1,35 @@
|
||||||
|
package function.builtin.math;
|
||||||
|
|
||||||
|
import function.ArgumentValidator;
|
||||||
|
import function.FunctionNames;
|
||||||
|
import function.LispFunction;
|
||||||
|
import function.builtin.math.DIVIDE.DivideByZeroException;
|
||||||
|
import sexpression.Cons;
|
||||||
|
import sexpression.LispNumber;
|
||||||
|
import sexpression.SExpression;
|
||||||
|
|
||||||
|
@FunctionNames({ "REM", "REMAINDER" })
|
||||||
|
public class REMAINDER extends LispFunction {
|
||||||
|
|
||||||
|
private ArgumentValidator argumentValidator;
|
||||||
|
|
||||||
|
public REMAINDER(String name) {
|
||||||
|
this.argumentValidator = new ArgumentValidator(name);
|
||||||
|
this.argumentValidator.setExactNumberOfArguments(2);
|
||||||
|
this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SExpression call(Cons argumentList) {
|
||||||
|
argumentValidator.validate(argumentList);
|
||||||
|
LispNumber dividend = (LispNumber) argumentList.getFirst();
|
||||||
|
LispNumber divisor = (LispNumber) ((Cons) argumentList.getRest()).getFirst();
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new LispNumber(dividend.getValue().remainder(divisor.getValue()));
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
throw new DivideByZeroException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -29,6 +29,7 @@ import function.builtin.math.MINUS;
|
||||||
import function.builtin.math.MODULO;
|
import function.builtin.math.MODULO;
|
||||||
import function.builtin.math.MULTIPLY;
|
import function.builtin.math.MULTIPLY;
|
||||||
import function.builtin.math.PLUS;
|
import function.builtin.math.PLUS;
|
||||||
|
import function.builtin.math.REMAINDER;
|
||||||
import function.builtin.predicate.ATOM;
|
import function.builtin.predicate.ATOM;
|
||||||
import function.builtin.predicate.EQ;
|
import function.builtin.predicate.EQ;
|
||||||
import function.builtin.predicate.EQUAL;
|
import function.builtin.predicate.EQUAL;
|
||||||
|
@ -98,6 +99,7 @@ public class FunctionTable {
|
||||||
allBuiltIns.add(PROGN.class);
|
allBuiltIns.add(PROGN.class);
|
||||||
allBuiltIns.add(QUOTE.class);
|
allBuiltIns.add(QUOTE.class);
|
||||||
allBuiltIns.add(RECUR.class);
|
allBuiltIns.add(RECUR.class);
|
||||||
|
allBuiltIns.add(REMAINDER.class);
|
||||||
allBuiltIns.add(REST.class);
|
allBuiltIns.add(REST.class);
|
||||||
allBuiltIns.add(SET.class);
|
allBuiltIns.add(SET.class);
|
||||||
allBuiltIns.add(SETQ.class);
|
allBuiltIns.add(SETQ.class);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package function.builtin.math;
|
package function.builtin.math;
|
||||||
|
|
||||||
|
import static testutil.TestUtilities.assertIsErrorWithMessage;
|
||||||
import static testutil.TestUtilities.assertSExpressionsMatch;
|
import static testutil.TestUtilities.assertSExpressionsMatch;
|
||||||
import static testutil.TestUtilities.evaluateString;
|
import static testutil.TestUtilities.evaluateString;
|
||||||
|
|
||||||
|
@ -85,17 +86,13 @@ public class MODULOTest extends SymbolAndFunctionCleaner {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = ModulusNotPositiveException.class)
|
@Test(expected = ModulusNotPositiveException.class)
|
||||||
public void divisorOfZero() {
|
public void negativeDivisor() {
|
||||||
String input = "(mod 5 0)";
|
evaluateString("(mod 5 -10)");
|
||||||
|
|
||||||
assertSExpressionsMatch(new LispNumber("0"), evaluateString(input));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = ModulusNotPositiveException.class)
|
@Test(expected = ModulusNotPositiveException.class)
|
||||||
public void negativeDivisor() {
|
public void divisorOfZero() {
|
||||||
String input = "(mod 5 -10)";
|
evaluateString("(mod 5 0)");
|
||||||
|
|
||||||
assertSExpressionsMatch(new LispNumber("0"), evaluateString(input));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = BadArgumentTypeException.class)
|
@Test(expected = BadArgumentTypeException.class)
|
||||||
|
@ -112,4 +109,9 @@ public class MODULOTest extends SymbolAndFunctionCleaner {
|
||||||
public void modWithTooManyArguments() {
|
public void modWithTooManyArguments() {
|
||||||
evaluateString("(mod 1 2 3)");
|
evaluateString("(mod 1 2 3)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void moduloNotPositiveException_HasCorrectAttributes() {
|
||||||
|
assertIsErrorWithMessage(new ModulusNotPositiveException());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
package function.builtin.math;
|
||||||
|
|
||||||
|
import static testutil.TestUtilities.assertSExpressionsMatch;
|
||||||
|
import static testutil.TestUtilities.evaluateString;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import function.ArgumentValidator.BadArgumentTypeException;
|
||||||
|
import function.ArgumentValidator.TooFewArgumentsException;
|
||||||
|
import function.ArgumentValidator.TooManyArgumentsException;
|
||||||
|
import function.builtin.math.DIVIDE.DivideByZeroException;
|
||||||
|
import sexpression.LispNumber;
|
||||||
|
import testutil.SymbolAndFunctionCleaner;
|
||||||
|
|
||||||
|
public class REMAINDERTest extends SymbolAndFunctionCleaner {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void rem() {
|
||||||
|
String input = "(rem 5 3)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("2"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void remainder() {
|
||||||
|
String input = "(remainder 11 7)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("4"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dividendGreaterThanDivisor() {
|
||||||
|
String input = "(rem 21 19)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("2"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dividendLessThanDivisor() {
|
||||||
|
String input = "(rem 5 239)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("5"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dividendEqualToDivisor() {
|
||||||
|
String input = "(rem 5 5)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("0"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dividendMultipleOfDivisor() {
|
||||||
|
String input = "(rem 20 5)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("0"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void divisorOfOne() {
|
||||||
|
String input = "(rem 5 1)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("0"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dividendOfZero() {
|
||||||
|
String input = "(rem 0 2309)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("0"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void negativeDividend() {
|
||||||
|
String input = "(rem -23 25)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("-23"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void negativeDivisor() {
|
||||||
|
String input = "(rem 5 -11)";
|
||||||
|
|
||||||
|
assertSExpressionsMatch(new LispNumber("0"), evaluateString(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = DivideByZeroException.class)
|
||||||
|
public void divisorOfZero() {
|
||||||
|
evaluateString("(rem 5 0)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = BadArgumentTypeException.class)
|
||||||
|
public void remWithNonNumber() {
|
||||||
|
evaluateString("(rem 'a 'b)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = TooFewArgumentsException.class)
|
||||||
|
public void remWithTooFewArguments() {
|
||||||
|
evaluateString("(rem 1)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = TooManyArgumentsException.class)
|
||||||
|
public void remWithTooManyArguments() {
|
||||||
|
evaluateString("(rem 1 2 3)");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue