ERights Home elang / scalars 
No Previous Sibling On to: float64 Type

Scalar Type:
integer


E's integers can represent any mathematical integer, no matter how big. These are often known as bignums, and is traditionally illustrated using recursive factorial:

? pragma.syntax("0.8")

? def factorial(n) :any {
>     if (n <= 0) {
>         1
>     } else {
>         n * factorial(n-1)
>     }
> }
# value: <factorial>

? factorial(3)
# value: 6

? factorial(30)
# value: 265252859812191058636308480000000

The above code uses a number of arithmetic operators. Here are the integer operators organized by precedence and associativity. Precedence and associativity determine how an expression involving multiple operators is to be read. For example, how should one read the following?

    x + y * u - w - z

E's answer is "((x + (y * u)) - w) - z", because

  1. * is higher precedence than + or -.
  2. + and - are the same precedence, and
  3. + and - are left associative.

Higher precedence means that it groups tighter than operators of lower precedence. Left associative means that it groups left-to-right. Non-associative means it doesn't group with itself. For example, in E you can't say "5 == 6 == 7" since == is non-associative.

Boolean Comparisons (non-associative)

Example Meaning Expansion Value
5 == 6 Are they the same? __equalizer.sameEver(5, 6) false
5 != 6 Are they different? __equalizer.sameEver(5, 6).not() true
5 & 6 bitwise-and 5 and(6) 4
5 | 6 bitwise-or 5 or(6) 7
5 ^ 6 bitwise-xor 5.xor(6) 3

On integers, these do just what you'd expect from any C-tradition language. Since E's integers are not precision limited, the bitwise operators see negative integers as having an infinite number of leading one bits, and the non-negative integers as having an infinite number of leading zero bits.

Magnitude Comparisons (non-associative)

Example Meaning Expansion Value
5 < 6 less than
5.compareTo(6) belowZero()
true
5 <= 6 less or equal to
5.compareTo(6) atMostZero()
true
5 >= 6 greater or equal to
5.compareTo(6) atLeastZero()
false
5 > 6 greater than
5.compareTo(6) aboveZero()
false

On integers, these have the conventional meaning.

Interval Expressions (non-associative)

Example Meaning Expansion Value
5..9 the integers from 5 inclusive to 9 inclusive __makeOrderedSpace.op__thru(5, 9) [5,6,7,8,9]
5..!9 the integers from 5 inclusive to 9 exclusive __makeOrderedSpace.op__till(5, 9) [5,6,7,8]

The interval expression makes it especially convenient to form interval objects. An interval object acts like a consecutive sequence of numbers, but uses a more compact representation. Intervals are useful, for example, in iteration:

? for i in 0..4 {
>     println(`i => ${factorial(i)}`)
> }
0 => 1
1 => 1
2 => 2
3 => 6
4 => 24

The reason for the strange syntax "..!" is that inclusive-exclusive intervals are often the most useful (and least accident prone) but have no natural notation. "x ..! y" can be thought of as "from x to, but not, y".

Bit Shift Expressions (left associative)

Example Meaning Expansion Value
5 << 3 arithmetic shift left 5.leftShift(3) 40
5 >> 1 arithmetic shift right 5.leftShift(-1) 2
Since E's integers are not precision limited, the "logical shift" that appears in some languages would be meaningless. As with the bitwise operators, negative numbers have an infinite supply of leading one bits and non-negative numbers have an infinite supply of leading zero bits.

Additive Expressions (left associative)

Example Meaning Expansion Value
5 + 6 addition 5.add(6) 11
5 - 6 subtraction 5.subtract(6) -1

As you'd expect.

Multiplicative Expressions (left associative)

Example Meaning Expansion Value
-5 * 3
multiplication
(-5).multiply(3)
-15
-5 / 3
floating-point division
(-5).approxDivide(3)
-1.66667
-5 // 3
integer division, rounding down
(-5).floorDivide(3)
-2
-5 % 3
remainder
(-5).remainder(3)
-2
-5 %% 3
modulo
(-5).mod(3)
1
2 ** 5 %% 3
modular exponentiation
2.modPow(5, 3)
2

Multiplication is add you'd expect. Division and remainder present an interesting problem. Integer division cannot of course be exact. E's "/" always gives the nearest floating point answer, even for cases that have an exact integer answer. E's "//" (pronounced "floor-divide") always gives the nearest integer not greater than the actual answer, ie, rounding towards negative infinity. By contrast, Java's "/" rounds towards zero. E's integers respond to the "truncDivide" message with this Java behavior. "%" is the remainder of truncDivide. "%%" is the remainder of "//", which is equivalent to the mathematical notion of modulo.

It turns out that modular exponentiation can be calculated vastly faster than the equivalent modulo of an exponentiation, so E's expansion recognizes this one case of a three-operand operator expression. Here's a useful demonstration of a mathematical discovery by Whit Diffee and Martin Hellman:

? def base := 2
# value: 2

? def mod := 3717
# value: 3717

? def JoeSecret := 298724
# value: 298724

? def JoePublic := base ** JoeSecret %% mod
# value: 3280

? def BettySecret := 378627
# value: 378627

? def BettyPublic := base ** BettySecret %% mod
# value: 8

? BettyPublic ** JoeSecret %% mod
# value: 631

? JoePublic ** BettySecret %% mod
# value: 631

If base and mod are publicly known, and if Joe and Betty each publicize only their calculated public numbers, then the above calculation shows them how they can calculate a new number, eg, 631, that they both agree on.

Joe Betty
? def base := 2
# value: 2

? def mod := 3717
# value: 3717

# publicize base & mod

? def JoeSecret := 298724
# value: 298724

? def JoePublic :=
>    base ** JoeSecret %% mod
# value: 3280
? def BettySecret := 378627
# value: 378627

? def BettyPublic :=
>    base ** BettySecret %% mod
# value: 8

# publicize JoePublic

# publicize BettyPublic

? BettyPublic ** JoeSecret %% mod
# value: 631
? JoePublic ** BettySecret %% mod
# value: 631

In the above example, base, mod, JoeSecret, and BettySecret were chosen by flinging my fingers at the keyboard. If instead they are chosen well, then no one who only knows base, mod, JoePublic, and BettyPublic will be able to calculate the number that Joe and Betty have come to agree on. This is known as Diffee Hellman Key Agreement.

Exercise for the reader: If the above example used larger numbers, would this web page be export controlled?

For the numerically savvy, there's another way in which "x ** y %% z" is better than "(x ** y) %% z", beyond being more efficient. If y is negative the latter expression doesn't make any sense (and throws an exception) while the former expression calculates "(x ** y.abs()).modInverse(z)", though once again, more efficiently.

Exponentiation Expression (non associative)

Example Meaning Expansion Value
3 ** 4
exponentiation
3.pow(4)
81

As you'd expect. Negative exponents are not allowed at this time.

Unary Expressions (left associative)

Example Meaning Expansion Value
- 5
twos-complement
5.negate()
-5
~5
bitwise-complement
5.complement()
-6

As you'd expect.


Additional integer Messages

In addition to the messages corresponding to the above operators, integers respond to the following messages.

? (-5).truncDivide(3)
# value: -1

"truncDivide" is integer division where the answer is rounded to an integer by rounding towards zero. It correspond to Java's "/" operator.

? (-5).ceil()
# value: -5
? (-5).floor()
# value: -5
? (-5).round()
# value: -5
? (-5).truncate()
# value: -5

On float64s, "ceil", "floor", "round", and "trunc" are used to get a corresponding integer. They are defined on integers as well to just return the integer itself. Why? That way, if you've got a number and you ask for an integer, it works even if you already have an integer.

? 33.asChar()
# value: '!'

Returns the character whose character code in unicode is 33.

? 33.asFloat64()
# value: 33.0

Converts to a floating point number.

? (-5).abs()
# value: 5

Absolute value.

? 248972.gcd(872346)
# value: 2

Greatest Common Divisor.


Integer Syntax

** To be written

 
Unless stated otherwise, all text on this page which is either unattributed or by Mark S. Miller is hereby placed in the public domain.
ERights Home elang / scalars 
No Previous Sibling On to: float64 Type
Download    FAQ    API    Mail Archive    Donate

report bug (including invalid html)

Golden Key Campaign Blue Ribbon Campaign