% is a proper modulus operator, not reminder. #fixes 842, #fixes 843

This commit is contained in:
gnembon committed 2021-05-10 00:49:04 -03:00
1 parent 6a06b0fb61
commit 451b35b6c5
3 files changed
+21 -4

No files matched your search

+10 -3
View File
@@ -143,6 +143,9 @@ in the output map.
Functional forms of `-` and `/` have less intuitive multi-nary interpretation, but they might be useful in some situations.
`x-y-z` resolves to `difference(x, y, z)`.
`/` always produces a properly accurate result, fully reversible with `*` operator. To obtain a integer 'div' result, use
`floor(x/y)`.
Examples:
<pre>
@@ -160,11 +163,15 @@ b = [100,63,100]; b+[10,0,10] => [110,63,110]
### Just Operators `%`, `^`
The modulo and exponent (power) operators work only if both operands are numbers
The modulo and exponent (power) operators work only if both operands are numbers. `%` is a proper (and useful) 'modulus' operator,
not a useless 'reminder' operator that you would expect from anything that touches Java. While typically modulus is reserved
to integer numbers, scarpet expands them to floats with as much sense as possible.
<pre>pi^pi%euler => 1.124....
-9 % 4 => -1
9 % -4 => 0 ¯\_(ツ)_/¯ Java
-9 % 4 => 3
9 % -4 => -3
9.1 % -4.2 => -3.5
9.1 % 4.2 => 0.7
-3 ^ 2 => 9
-3 ^ pi => // Error
</pre>
@@ -80,7 +80,7 @@ public class Operators {
expression.addFunctionalEquivalence("/", "quotient");
expression.addBinaryOperator("%", precedence.get("multiplication*/%"), true, (v1, v2) ->
new NumericValue(NumericValue.asNumber(v1).getDouble() % NumericValue.asNumber(v2).getDouble()));
NumericValue.asNumber(v1).mod(NumericValue.asNumber(v2)));
expression.addBinaryOperator("^", precedence.get("exponent^"), false, (v1, v2) ->
new NumericValue(java.lang.Math.pow(NumericValue.asNumber(v1).getDouble(), NumericValue.asNumber(v2).getDouble())));
@@ -313,4 +313,14 @@ public class NumericValue extends Value
{
return longValue!= null || getDouble() == (double)getLong();
}
public Value mod(NumericValue n2)
{
if (this.longValue != null && n2.longValue != null)
return new NumericValue(Math.floorMod(longValue, n2.longValue));
double x = value;
double y = n2.value;
if (y == 0) throw new ArithmeticException("Division by zero");
return new NumericValue( x - Math.floor(x / y) * y);
}
}