dwayne / elm-integer / Integer

Compute with the integers, ℤ = { ..., -2, -1, 0, 1, 2, ... }.

Representation


type Integer

A representation of the integers.

If you must know, it uses a sign-magnitude representation.

N.B. The size of the numbers you can compute with is only limited by the available memory.

Constants

The integers from -10 to 10 inclusive are named.

zero : Integer

The integer 0.

To be more precise, it is a representation of the integer 0. However, I will not have any cause to make that distinction. A similar remark can be made about the other constants.

one : Integer

The integer 1.

two : Integer

The integer 2.

three : Integer

The integer 3.

four : Integer

The integer 4.

five : Integer

The integer 5.

six : Integer

The integer 6.

seven : Integer

The integer 7.

eight : Integer

The integer 8.

nine : Integer

The integer 9.

ten : Integer

The integer 10.

negativeOne : Integer

The integer -1.

negativeTwo : Integer

The integer -2.

negativeThree : Integer

The integer -3.

negativeFour : Integer

The integer -4.

negativeFive : Integer

The integer -5.

negativeSix : Integer

The integer -6.

negativeSeven : Integer

The integer -7.

negativeEight : Integer

The integer -8.

negativeNine : Integer

The integer -9.

negativeTen : Integer

The integer -10.

Limits

Let n : Int. If minSafeInt <= n <= maxSafeInt then n is called a safe Int.

maxSafeInt : Basics.Int

The largest Int, currently 2^53 - 1 = 9007199254740991, which can be given as input to fromSafeInt and fromInt without causing problems.

minSafeInt : Basics.Int

The smallest Int, currently -2^53 + 1 = -9007199254740991, which can be given as input to fromSafeInt and fromInt without causing problems.

Constructors

fromSafeInt : Basics.Int -> Integer

Use this function when you know the given Int is a safe Int.

fromSafeInt 0 == zero

fromSafeInt 1 == one

fromSafeInt -1 == negativeOne

fromSafeInt maxSafeInt == fromSafeString "9007199254740991"

fromSafeInt minSafeInt == fromSafeString "-9007199254740991"

If the given Int isn't safe then zero is returned.

fromSafeInt (minSafeInt - 1) == zero

fromSafeInt (maxSafeInt + 1) == zero

This function is useful for establishing small constants in a calculation. For e.g. to compute the first 100 digits of π using John Machin's formula the integer 239 is needed.

twoThirtyNine : Integer
twoThirtyNine =
    fromSafeInt 239

fromInt : Basics.Int -> Maybe Integer

Create the integer that represents the given Int.

fromInt 0 == Just zero

fromInt 1 == Just one

fromInt -1 == Just negativeOne

fromInt maxSafeInt == fromString "9007199254740991"

fromInt minSafeInt == fromString "-9007199254740991"

Unless the given Int is less than minSafeInt or greater than maxSafeInt.

fromInt (minSafeInt - 1) == Nothing

fromInt (maxSafeInt + 1) == Nothing

fromNatural : Natural -> Integer

If you happen to have a natural number at hand then you can convert it to an integer using this function.

For all n : Natural:

fromSafeString : String -> Integer

It's best to use this function when you can guarantee that the string you're dealing with is a valid input to the fromString function.

If the input is invalid then zero is returned.

N.B. Read the documentation of fromString to learn what's considered to be valid or invalid input to this function.

This function is useful for establishing large constants in a calculation.

oneGoogol : Natural
oneGoogol =
    -- 10 ^ 100
    fromSafeString "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"

Learn more about a googol.

What's considered a large constant?

Let n : Int, since fromSafeInt n can be used for minSafeInt <= n <= maxSafeInt then it makes sense to consider any integer smaller than minSafeInt or larger than maxSafeInt, a large constant.

fromString : String -> Maybe Integer

Create the integer represented by the given signed string.

Syntax for fromString input

input    ::= signed
signed   ::= -? unsigned
unsigned ::= ('0b' | '0B') binary
           | ('0o' | '0O') octal
           | ('0x' | '0X') hex
           | decimal
binary   ::= [0-1]+
octal    ::= [0-7]+
hex      ::= [0-9a-fA-F]+
decimal  ::= [0-9]+

For e.g.

fromString "0b10101101" == fromInt 173

fromString "-0o255" == fromInt -173

fromString "0XaD" == fromInt 173

fromString "173" == fromInt 173

fromString "b10101101" == Nothing
-- Because the leading '0' is missing.

fromString "-aD" == Nothing
-- Because 'a' is not a decimal digit.

fromString "0x" == Nothing
-- Because there must be at least one hexadecimal digit.

fromBinaryString : String -> Maybe Integer

Create the integer represented by the given signed binary string.

binary ::= -? [0-1]+

For e.g.

fromBinaryString "0" == Just zero

fromBinaryString "1010" == Just ten

fromBinaryString "-1010" == Just negativeTen

fromBinaryString "" == Nothing
-- Because the string is empty.

fromBinaryString "-" == Nothing
-- Because there must be at least one binary digit.

fromBinaryString "2" == Nothing
-- Because '2' is not a binary digit.

fromOctalString : String -> Maybe Integer

Create the integer represented by the given signed octal string.

octal ::= -? [0-7]+

For e.g.

fromOctalString "0" == Just zero

fromOctalString "12" == Just ten

fromOctalString "-12" == Just negativeTen

fromOctalString "" == Nothing
-- Because the string is empty.

fromOctalString "-" == Nothing
-- Because there must be at least one octal digit.

fromOctalString "8" == Nothing
-- Because '8' is not an octal digit.

fromDecimalString : String -> Maybe Integer

Create the integer represented by the given signed decimal string.

decimal ::= -? [0-9]+

For e.g.

fromDecimalString "0" == Just zero

fromDecimalString "10" == Just ten

fromDecimalString "-10" == Just negativeTen

fromDecimalString "" == Nothing
-- Because the string is empty.

fromDecimalString "-" == Nothing
-- Because there must be at least one decimal digit.

fromDecimalString "A" == Nothing
-- Because 'A' is not a decimal digit.

fromHexString : String -> Maybe Integer

Create the integer represented by the given signed hexadecimal string.

hex ::= -? [0-9a-fA-F]+

For e.g.

fromHexString "0" == Just zero

fromHexString "a" == Just ten

fromHexString "-A" == Just negativeTen

fromHexString "" == Nothing
-- Because the string is empty.

fromHexString "-" == Nothing
-- Because there must be at least one hexadecimal digit.

fromHexString "5g" == Nothing
-- Because 'g' is not a hexadecimal digit.

fromBaseBString : Basics.Int -> String -> Maybe Integer

Create the integer represented by the given signed base-b string.

b must be between 2 and 36 inclusive and each character in the string must be a valid base-b digit.

About base-b digits

A valid base-b digit is any digit d such that 0 <= d <= b - 1.

For bases larger than 10, you can use case-insensitive letters from the Latin alphabet to represent the base-b digits that are 10 or larger. So,

A or a represents 10
B or b represents 11
C or c represents 12
...
Z or z represents 35

For e.g.

If b = 16 then the valid base-16 digits are [0-9a-fA-F].

If b = 36 then the valid base-36 digits are [0-9a-zA-Z].

Syntax for fromBaseBString input

input ::= -? [digit]+
digit ::= [0-9a-zA-Z]

Valid strings when b = 16:

"0", "-0", "123", "-123", and "-Ff".

Invalid strings when b = 16:

Examples

fromBaseBString 2 "1010" == Just ten

fromBaseBString 2 "-1010" == Just negativeTen

fromBaseBString 16 "aD" == fromInt 173

fromBaseBString 36 "z" == fromInt 35

fromBaseBString 2 "" == Nothing
-- Because the string is empty.

fromBaseBString 8 "-" == Nothing
-- Because there must be at least one octal digit.

fromBaseBString 10 "A" == Nothing
-- Because 'A' is not a decimal digit.

Comparison

To test for equality between two integers you can use == and /=.

add negativeFive two == negativeThree

mul negativeThree negativeThree /= negativeNine

For all other comparisons you will have to use the functions below.

compare : Integer -> Integer -> Basics.Order

Compare any two integers.

compare negativeFive negativeTwo == LT

compare two two == EQ

compare five negativeTen == GT

isLessThan : Integer -> Integer -> Basics.Bool

Determine if the second integer is less than the first.

(negativeFive |> isLessThan negativeTwo) == True

(two |> isLessThan two) == False

(five |> isLessThan negativeTen) == False

isLessThanOrEqual : Integer -> Integer -> Basics.Bool

Determine if the second integer is less than or equal to the first.

(negativeFive |> isLessThanOrEqual negativeTwo) == True

(two |> isLessThanOrEqual two) == True

(five |> isLessThanOrEqual negativeTen) == False

isGreaterThan : Integer -> Integer -> Basics.Bool

Determine if the second integer is greater than the first.

(negativeFive |> isGreaterThan negativeTwo) == False

(two |> isGreaterThan two) == False

(five |> isGreaterThan negativeTen) == True

isGreaterThanOrEqual : Integer -> Integer -> Basics.Bool

Determine if the second integer is greater than or equal to the first.

(negativeFive |> isGreaterThanOrEqual negativeTwo) == False

(two |> isGreaterThanOrEqual two) == True

(five |> isGreaterThanOrEqual negativeTen) == True

max : Integer -> Integer -> Integer

Find the larger of two integers.

max five negativeTen == five

max negativeFive negativeTwo == negativeTwo

min : Integer -> Integer -> Integer

Find the smaller of two integers.

min five negativeTen == negativeTen

min negativeFive negativeTwo == negativeFive

Predicates

isNegative : Integer -> Basics.Bool

Determine if the integer is negative (i.e. less than 0).

isNegative negativeTwo == True

isNegative zero == False

isNegative two == False

isNonNegative : Integer -> Basics.Bool

Determine if the integer is non-negative (i.e. not negative, so greater than or equal to 0).

isNonNegative negativeTwo == False

isNonNegative zero == True

isNonNegative two == True

isZero : Integer -> Basics.Bool

Determine if the integer is 0.

isZero zero == True

isZero negativeSeven == False

isZero six == False

isNonZero : Integer -> Basics.Bool

Determine if the integer is non-zero (i.e. not 0, so either positive or negative).

isNonZero zero == False

isNonZero negativeSeven == True

isNonZero six == True

isPositive : Integer -> Basics.Bool

Determine if the integer is positive (i.e. greater than 0).

isPositive five == True

isPositive zero == False

isPositive negativeEight == False

isNonPositive : Integer -> Basics.Bool

Determine if the integer is non-positive (i.e. not positive, so less than or equal to 0).

isNonPositive five == False

isNonPositive zero == True

isNonPositive negativeEight == True

isEven : Integer -> Basics.Bool

Determine if the integer is even (i.e. divisible by 2).

isEven zero == True

isEven negativeFour == True

isEven eight == True

isEven three == False

isEven negativeNine == False

isOdd : Integer -> Basics.Bool

Determine if the integer is odd (i.e. not even, so not divisible by 2).

isOdd zero == False

isOdd negativeFour == False

isOdd eight == False

isOdd three == True

isOdd negativeNine == True

Arithmetic

abs : Integer -> Integer

Compute the absolute value of the given integer. If you want it as a natural number, use toNatural.

You can think of the absolute value of an integer as its distance from 0.

abs zero == zero

abs five == five

abs negativeFive = five
-- Because 5 and -5 are the same distance away from 0.

negate : Integer -> Integer

Compute the additive inverse of the given integer.

The additive inverse of an integer, z, is the integer that, when added to z, yields 0.

negate five == negativeFive
-- Because 5 + (-5) = 0.

negate negativeFive == five
-- Because -5 + 5 = 0.

negate zero == zero
-- Becase 0 + 0 = 0.

add : Integer -> Integer -> Integer

Add two integers.

sub : Integer -> Integer -> Integer

Subtract the second integer from the first.

sub ten four == six
-- 10 - 4 = 6

sub four ten == negativeSix
-- 4 - 10 = -6

mul : Integer -> Integer -> Integer

Multiply two integers.

divModBy : Integer -> Integer -> Maybe ( Integer, Integer )

Find the quotient and remainder when the second integer (the dividend) is divided by the first (the divisor).

divModBy d D of two integers D and d ≠ 0, is defined as producing two unique integers q (the quotient) and r (the remainder) such that

For e.g.

(ten |> divModBy two) == Just ( five, zero )

(ten |> divModBy negativeTwo) == Just ( negativeFive, zero )

(negativeTen |> divModBy two) == Just ( negativeFive, zero )

(negativeTen |> divModBy negativeTwo) == Just ( five, zero )

(ten |> divModBy three) == Just ( three, one )

(ten |> divModBy negativeThree) == Just ( negativeThree, one )

(negativeTen |> divModBy three) == Just ( negativeFour, two )

(negativeTen |> divModBy negativeThree) == Just ( four, two )

Division by 0 is not allowed. So, for all z : Integer,

(z |> divModBy zero) == Nothing

N.B. divModBy defines Euclidean division (or E-division) according to Daan Leijen's paper, Division and Modulus for Computer Scientists.

divBy : Integer -> Integer -> Maybe Integer

Find the quotient when the second integer is divided by the first.

N.B. Please see divModBy to understand how the quotient is computed.

modBy : Integer -> Integer -> Maybe Integer

Find the remainder when the second integer is divided by the first.

N.B. Please see divModBy to understand how the remainder is computed.

quotRemBy : Integer -> Integer -> Maybe ( Integer, Integer )

Find the quotient and remainder when the second integer (the dividend) is divided by the first (the divisor).

quotRemBy d D of two integers D and d ≠ 0, is defined as producing two unique integers q (the quotient) and r (the remainder) such that

For e.g.

(ten |> quotRemBy two) == Just ( five, zero )

(ten |> quotRemBy negativeTwo) == Just ( negativeFive, zero )

(negativeTen |> quotRemBy two) == Just ( negativeFive, zero )

(negativeTen |> quotRemBy negativeTwo) == Just ( five, zero )

(ten |> quotRemBy three) == Just ( three, one )

(ten |> quotRemBy negativeThree) == Just ( negativeThree, one )

(negativeTen |> quotRemBy three) == Just ( negativeThree, negativeOne )

(negativeTen |> quotRemBy negativeThree) == Just ( three, negativeOne )

Division by 0 is not allowed. So, for all z : Integer,

(z |> quotRemBy zero) == Nothing

N.B. quotRemBy defines truncated division (or T-division) according to Daan Leijen's paper, Division and Modulus for Computer Scientists.

quotBy : Integer -> Integer -> Maybe Integer

Find the quotient when the second integer is divided by the first.

N.B. Please see quotRemBy to understand how the quotient is computed.

remBy : Integer -> Integer -> Maybe Integer

Find the remainder when the second integer is divided by the first.

N.B. Please see quotRemBy to understand how the remainder is computed.

exp : Integer -> Natural -> Integer

Integer exponentiation. Find the power of the integer (the base) to the natural number (the exponent).

Given,

import Natural as N

Then,

exp two N.three == eight

exp negativeTwo N.three == negativeEight

For all z : Integer,

exp z N.zero == one

In particular,

exp zero N.zero == one

N.B. You can read "What is 0^0?" to learn more.

For all n : Natural, where n is positive,

exp zero n == zero

Conversion

toInt : Integer -> Basics.Int

Convert any integer, z, to sign z * (|z| mod (maxSafeInt + 1)), where

sign z =
    -1 if z < 0
     0 if z = 0
     1 if z > 0

For e.g.

toInt zero == 0

toInt ten == 10

toInt negativeTen == -10

toInt (fromSafeInt maxSafeInt) == maxSafeInt

toInt (fromSafeInt minSafeInt) == minSafeInt

toInt (add (fromSafeInt maxSafeInt) one) == 0

toInt (add (fromSafeInt maxSafeInt) ten) == 9

toInt (sub (fromSafeInt minSafeInt) one) == 0

toInt (sub (fromSafeInt minSafeInt) ten) == -9

toNatural : Integer -> Natural

Compute the absolute value of the given integer as a natural number. If you want an integer, use abs.

toString : Integer -> String

An alias for toDecimalString.

toBinaryString : Integer -> String

Convert any integer to its signed binary (base-2) representation.

toBinaryString zero == "0"

toBinaryString one == "1"

toBinaryString ten == "1010"

toBinaryString negativeTen == "-1010"

toBinaryString (fromSafeInt -1729) == "-11011000001"

toBinaryString (add (fromSafeInt maxSafeInt) one) == "100000000000000000000000000000000000000000000000000000"

toBinaryString (sub (fromSafeInt minSafeInt) one) == "-100000000000000000000000000000000000000000000000000000"

toOctalString : Integer -> String

Convert any integer to its signed octal (base-8) representation.

toOctalString zero == "0"

toOctalString one == "1"

toOctalString ten == "12"

toOctalString negativeTen == "-12"

toOctalString (fromSafeInt -1729) == "-3301"

toOctalString (add (fromSafeInt maxSafeInt) one) == "400000000000000000"

toOctalString (sub (fromSafeInt minSafeInt) one) == "-400000000000000000"

toDecimalString : Integer -> String

Convert any integer to its signed decimal (base-10) representation.

toDecimalString zero == "0"

toDecimalString one == "1"

toDecimalString ten == "10"

toDecimalString negativeTen == "-10"

toDecimalString (fromSafeInt -1729) == "-1729"

toDecimalString (add (fromSafeInt maxSafeInt) one) == "9007199254740992"

toDecimalString (sub (fromSafeInt minSafeInt) one) == "-9007199254740992"

toHexString : Integer -> String

Convert any integer to its signed hexadecimal (base-16) representation.

toHexString zero == "0"

toHexString one == "1"

toHexString ten == "A"

toHexString negativeTen == "-A"

toHexString (fromSafeInt -1729) == "-6C1"

toHexString (add (fromSafeInt maxSafeInt) one) == "20000000000000"

toHexString (sub (fromSafeInt minSafeInt) one) == "-20000000000000"

toBaseBString : Basics.Int -> Integer -> Maybe String

Convert any integer to its signed base-b representation.

b must be between 2 and 36 inclusive and each character in the resulting string will be a valid base-b digit.

All Latin letters in the base-b representation will be uppercased.

For e.g.

toBaseBString 2 (fromSafeInt 1729) == Just "11011000001"

toBaseBString 8 (fromSafeInt -1729) == Just "-3301"

toBaseBString 10 (fromSafeInt 1729) == Just "1729"

toBaseBString 16 (fromSafeInt -1729) == Just "-6C1"

toBaseBString 36 (fromSafeInt 1729) == Just "1C1"

For any k : Int where k < 2 or k > 36, and any z : Integer,

toBaseBString k z == Nothing

N.B. Please refer to fromBaseBString to learn more about base-b digits.