Chapter 19: Numbers
The topics covered in this chapter are:
 The different kinds of numbers available in J
 Special numbers (infinities and indeterminates)
 Notations for writing numbers
 How numbers are displayed
19.1 Six Different Kinds of Numbers
J supports computation with numbers of these kinds:
 booleans (or truthvalues)
 integers
 real (or floatingpoint) numbers
 complex numbers
 extended integers (that is, arbitrarily large integers exactly represented)
 rationals (that is, pairs of extended integers)
Each kind of number has its own internal representation in
memory. For example,
an array containing only the truthvalues 0 and 1
is stored in a compact internal form, called "boolean",
rather
than in the floatingpoint form.
Similarly an array containing only (relatively small)
whole numbers is stored in a compact form
called "integer".
The choice of appropriate representation
is managed entirely automatically by the J system,
and is not normally something the programmer must be aware of.
However, there is a means of testing
the representation of a number. Here is a utility function for the purpose.
types =: 'bool';'int';'float';'complex';'ext int';'rational'
type =: > @: ({ & types) @: (1 4 8 16 64 128 & i.) @: (3 !: 0)
type 0=0 
type 37 
type 2.5 
type 12345678901 
bool 
int 
float 
float 
19.1.1 Booleans
There are builtin functions for logical computation with
boolean values.
Giving conventional names to these functions:
and =: *.
or =: +.
not =: .
notand =: *:
notor =: +:
we can show their truthtables:
p =: 4 1 $ 0 0 1 1
q =: 4 1 $ 0 1 0 1
p 
q 
p and q 
p or q 
not p 
p notand q 
0
0
1
1 
0
1
0
1 
0
0
0
1 
0
1
1
1 
1
1
0
0 
1
1
1
0 
Further logical functions can be defined in the usual way.
For example, logical implication, with the scheme
p implies q means not (p and not q)
is defined by not composed with the hook and not
imp =: not @ (and not)
p 
q 
p imp q 
0
0
1
1 
0
1
0
1 
1
1
0
1 
We regard the booleans as numbers because they can
be interpreted as having arithmetic values. To illustrate,
implication has the same truthtable as
lessthanorequal:
p imp q 
p <: q 
1
1
0
1 
1
1
0
1 
For another example of booleans as numbers,
the sum of the positive numbers in a list is shown by:
z =: 3 _1 4 
b =: z > 0 
b * z 
+/ b * z 
3 _1 4 
1 0 1 
3 0 4 
7 
19.1.2 Integers
On a 32bit machine integers range between
_2147483648 and 2147483647.
The result of arithmetic with integers is converted to
floatingpoint if larger than the maximum integer.
maxint=:2147483647 
type maxint 
z =: 1+maxint 
type z 
2147483647 
int 
2.14748e9 
float 
19.1.3 FloatingPoint Numbers
A floatingpoint number is a number represented in the computer in such a way that:
(1) there may be a a fractional part as well as a wholenumber part.
(2) a fixed amount of computer storage is occupied by the number, whatever the value of the number.
and therefore (3) the precision with which the number is represented is limited to
at most about 17 significant decimal digits (on a PC).
Examples of floatingpoint numbers are 0.25 2.5 12345678901
We will use the term "real" more or less interchangeably with "floatingpoint".
19.1.4 Scientific Notation
What is sometimes called "scientific notation"
is a convenient way of writing
very large or very small numbers.
For example, 1500000 may be written as 1.5e6,
meaning 1.5 * 10^6.
The general scheme is that a number written in the form XeY, where Y is a
(positive or negative) integer means (X * 10^Y).
3e2 
1.5e6 
1.5e_4 
300 
1500000 
0.00015 
Note that in 3e2 the letter e is not any kind of function;
it is part of the notation for writing numbers,
just as a decimal point is part of the notation.
We say that the string of characters 3 followed by e followed by 2 is a numeral
which denotes the number 300.
The string of characters 3 followed by 0
followed by 0 is another numeral denoting the same number.
Different forms of numerals provide convenient ways to express
different numbers. A number expressed by a numeral is also called a "constant"
(as opposed to a variable.)
We will come back to the topic of numerals: now we return to the topic
of different kinds of numbers.
19.1.5 Comparison of FloatingPoint Numbers
Two numbers are regarded as equal if their difference is relatively small.
For example, we see that a and b have a nonzero difference,
but even so the expression a = b produces "true".
a =: 1.001 
b =: a  2^_45 
a  b 
a = b 
1.001 
1.001 
2.84217e_14 
1 
If we say that the "relative difference" of two numbers is
the magnitude of the difference divided by the magnitude of the larger,
RD =: ( @: ) % ( @: >.)
then for a=b to be true, the relative difference
(a RD b) must not exceed a small value
called the "comparison tolerance" which is by default 2^_44
a RD b 
2^_44 
a = b 
2.83933e_14 
5.68434e_14 
1 
Thus to compare two numbers we need to compare relative difference with tolerance.
The latter comparison is itself strict, that is, does not involve any tolerance.
Zero is not tolerantly equal to
any nonzero number, no matter how small,
because the relative difference must be
1, and thus greater than tolerance.
tiny =: 1e_300 
tiny = 0 
tiny RD 0 
1e_300 
0 
1 
However, 1+tiny is tolerantly equal to 1.
tiny 
tiny = 0 
1 = tiny + 1 
1e_300 
0 
1 
The value of the comparison tolerance currently in effect
is given by the builtin verb
9!:18 applied to a null argument. It is currently 2^_44.
9!:18 '' 
2^_44 
5.68434e_14 
5.68434e_14 
Applying the builtin
verb 9!:19 to an argument y sets the tolerance to y
subsequently.
The following example shows that when the
tolerance is 2^_44, then
a = b but when the tolerance is set to zero
it is no longer the case that a = b.
(9!:19) 2^_44 
a = b 
(9!:19) 0 
a = b 

1 

0 
The tolerance queried by 9!:18 and set by 9!:19 is a global
parameter, influencing the outcome of computations with =.
A verb to apply a specified tolerance t, regardless of the global parameter,
can be written as = !. t. For example, strict (zerotolerance) equality
can be defined by:
streq =: = !. 0
Resetting the global tolerance to the default value, we see:
(9!:19) 2^_44 
a  b 
a = b 
a streq b 

2.84217e_14 
1 
0 
Comparison with = is tolerant,
and so are comparisons with <, <:, >, >:, ~: and :.
For example, the difference ab is positive but too small to make it true that
a>b
a  b 
a > b 
2.84217e_14 
0 
Permissible tolerances range between 0 and 2^_35.
That is, an attempt to set the tolerance larger
than 2^_35 is an error:
(9!:19) 2^_35 
(9!:19) 2^_34 

error 
The effect of disallowing large tolerances
is that no two different integers compare equal when
converted to floatingpoint.
19.1.6 Complex Numbers
The square root of 1 is the imaginary number conventionally
called "i".
A complex number which is conventionally written as,
for example, 3+i4 is in J written as 3j4.
In J an imaginary number is always regarded as a
complex number with real part zero.
Thus "i", the square root of 1, can be
written 0j1.
i =: %: _1 
i * i 
0j1 * 0j1 
0j1 
_1 
_1 
A complex number can be built from two separate real numbers by arithmetic
in the ordinary way,
or more conveniently with the builtin function j. (lowercase j dot, called
"Complex").
3 + 0j1 * 4 
3 j. 4 
3j4 
3j4 
A complex number such as 3j4 is a single number, a scalar. To extract
its real part and imaginary part separately we can use the builtin verb
+.(plus dot, called "Real/Imaginary").
To extract separately the magnitude and angle (in radians) we can use the
builtin verb *. (asterisk dot, called "Length/Angle").
+. 3j4 
*. 3j4 
3 4 
5 0.927295 
Given a magnitude and angle, we can build a complex number
by taking sine and cosine, or more conveniently with the builtin
function r. (lowercase r dot, called "Polar").
sin =: 1 & o.
cos =: 2 & o.
mag =: 5
ang =: 0.92729522 NB. radians
mag * (cos ang) + 0j1 * sin ang 
mag r. ang 
3j4 
3j4 
A complex constant with magnitude X and angle (in radians) Y
can be written in the form
XarY, meaning X r. Y. Similarly, if the angle is given in degrees,
we can write XadY.
5ar0.9272952 
5ad53.1301 
3j4 
3j4 
19.1.7 Extended Integers
A floatingpoint number, having a limited storage space in the computer's memory,
can represent an integer exactly only up to about 17 digits.
For exact computations with longer numbers, "extended integers" are available.
An "extended integer" is a number which exactly represents an integer no matter how many digits are needed.
An extended integer is written with the digits followed with the letter 'x'. Compare the following:
a =: *: 10000000001 
b =: *: 10000000001x 
1e20 
100000000020000000001 
Here a is an approximation while b is an exact result.
type a 
type b 
float 
ext int 
We can see that adding 1 to a makes no difference, while adding 1 to b does make a difference:
(a + 1)  a 
(b + 1)  b 
0 
1 
19.1.8 Rational Numbers
A "rational number" is a single number which represents exactly the ratio of two
integers, for example, twothirds is the ratio of 2 to 3. Twothirds
can be written as a rational number with the notation 2r3.
The point of rationals is that they are are exact representations
using extended integers. Arithmetic with rationals gives exact results.
2r3 + 1r7 
2r3 * 4r7 
2r3 % 5r7 
17r21 
8r21 
14r15 
Rationals can be constructed by dividing extended integers.
Compare the following:
2 % 3 
2x % 3x 
0.666667 
2r3 
A rational can be constructed from a given floatingpoint
number with the verb x:
A rational number can be converted to a floatingpoint approximation with the inverse ofx: , that is, verb x: ^: _1
float =: x: ^: _1 
float 2r3 
++++
x:^:_1
++++ 
0.666667 
Given a rational number, its numerator and denominator can
be recovered with the verb 2 & x:, which gives a list of length 2.
nd =: 2 & x: 
nd 2r3 
++++
2&x:
++++ 
2 3 
19.1.9 Type Conversion
We have numbers of six different types:
boolean, integer, extended integer, rational, floatingpoint and complex.
Arithmetic can be done with a mixture of types.
For example an integer plus an extended gives an extended,
and a rational times a float gives a float.
1 + 10^19x 
1r3 * 0.75 
10000000000000000001 
0.25 
The general scheme is that the six types
form a progression: from boolean
to integer to extended to rational to floatingpoint to complex.
We say that boolean is the simplest or "lowest" type
and complex as the most general or "highest" type
Where we have two numbers of different types,
the one of lower type is converted to match the type of the higher.
and the result is of the "higher".
type 1r3 
type 1%3 
z =: 1r3, 1%3 
type z 
rational 
float 
0.333333 0.333333 
float 
19.2 Special Numbers
19.2.1 "Infinity"
A floatingpoint number can (on a PC) be no larger than about 1e308,
because of the way it is stored in the computer's memory.
Any arithmetic which attempts to produce a larger result
will in fact produce a special number called "infinity"
and written _ (underscore). For example:
1e308 * 0 1 2 
1e400 
1 % 0 
0 1e308 _ 
_ 
_ 
There is also
"negative infinity" written as __ (underscore underscore).
Infinity is a floatingpoint number:
type _
float
19.2.2 Indeterminate Numbers
Infinity is equal to infinity.
However, infinity minus infinity is
not zero but rather a special number called
"indeterminate",
written as _. (underscore dot)
Indeterminate is equal to indeterminate.
However indeterminate minus indeterminate
is not zero but indeterminate.
Computations with indeterminate may
produce surprising results.
Thus indeterminate is not to be regarded as extending
the meaning of "number" according to
some extended axiomatization of arithmetic.
Rather, the view is recommended
that the only purpose of indeterminate
is as a signal of numerical error when it occurs in the
result of a computation.
Infinity is equal to itself and
nothing else, and the same is true of
indeterminate. Thus we have a reliable (that is,
determinate) test for occurrences.
z =: 1 _ _. 
z = 1 
z = _ 
z = _. 
1 _ _. 
1 0 0 
0 1 0 
0 0 1 
19.3 Notations for Numerals
We have seen above numerals formed with the letters e, r and j, for example:
1e3, 2r3, and 3j4. Here we look at more letters for forming numerals.
A numeral written with letter p, of the form XpY means X * pi ^ Y
where pi is the familiar value 3.14159265....
pi =: 1p1 
twopi =: 2p1 
2p_1 
3.14159 
6.28319 
0.63662 
Similarly, a numeral written with letter x, of the form XxY means X * e ^ Y
where e is the familiar value 2.718281828....
e =: 1x1 
2x_1 
2 * e ^ _1 
2.71828 
0.735759 
0.735759 
These p and x forms of numeral provide a convenient way of writing constants
accurately without writing out many digits.
Finally, we can write numerals with a base other than 10.
For example the binary or base2 number with binary digits 101 has the value 5
and can be written as 2b101.
2b101
5
The general scheme is that NbDDD.DDD is a numeral in numberbase N with digits DDD.DDD .
With bases larger than 10, we will need
digits larger than 9, so we take letter 'a' as a digit with value 10, 'b' with value 11,
and so on up to 'z' with value 35.
For example, letter 'f' has digitvalue 15, so in hexadecimal (base 16) the
numeral written 16bff has the value 255.
The numberbase N is given in decimal.
16bff 
(16 * 15) + 15 
255 
255 
One more example. 10b0.9 is evidently a base10 number meaning "ninetenths" and so,
in base 20, 20b0.f means "fifteen twentieths"
10b0.9 20b0.f
0.9 0.75
19.3.1 Combining the Notations
The notationletters e, r, j ar ad p
x and b may be used in combination.
For example we can write 1r2p1
to mean "pi over two". Here are some further examples
of possible combinations.
A numeral in the form XrY denotes the number
X%Y. A numeral in the form XeYrZ denotes
the number (XeY) % Z because e is considered before r.
1.2e2 
(1.2e2) % 4 
1.2e2r4 
120 
30 
30 
A numeral in the form XjY denotes the complex number
(X j. Y) (that is, (X + (%: _1) * Y).
A numeral in the form XrYjZ denotes the number
(XrY) j. Z because r is considered before j
3r4 
(3r4) j. 5 
3r4j5 
3r4 
0.75j5 
0.75j5 
A numeral in the form XpY denotes the number
X*pi^Y. A numeral in the form XjYpZ denotes
(XjY) *pi^Z because j is considered before p.
3j4p5 
(3j4) * pi ^ 5 
918.059j1224.08 
918.059j1224.08 
A numeral in the form XbY denotes the number
YinbaseX. A numeral in the form XpYbZ
denotes the number Zinbase(XpY) because
p is considered before b.
(3*pi)+5 
1p1b35 
14.4248 
14.4248 
19.4 How Numbers are Displayed
A number is displayed by J with, by default, up to 6 or 7
significant digits.
This means that, commonly, small integers are shown exactly,
while large numbers, or numbers with many
significant digits, are shown approximately.
10 ^ 3 
2.7182818285 
2.718281828 * 10 ^ 7 
1000 
2.71828 
2.71828e7 
The number of significant digits used
for display is determined by a global variable
called the "printprecision". If we define
the two functions:
ppq =: 9 !: 10 NB. printprecision query
pps =: 9 !: 11 NB. printprecision set
then the expression ppq '' gives the value
of printprecision currently in effect, while
pps n will set the printprecision to n.
ppq '' 
e =: 2.718281828 
pps 8 
e 
6 
2.71828 

2.7182818 
19.4.1 The "Format" Verb
There is a builtin verb ":
(doublequote colon, called "Format").
Monadic Format converts a number into a string
representing the number with the printprecision
currently in effect. In the following example,
note that a is a scalar,
while the formatted representation of a is a list of characters.
a =: 1 % 3 
": a 
$ ": a 
0.33333333 
0.33333333 
10 
The argument can be a list of numbers and the result is
a single string.
b =: 1 % 3 4 
": b 
$ b 
$ ": b 
0.33333333 0.25 
0.33333333 0.25 
2 
15 
Dyadic Format allows more control over the
representation.
The left argument is complex: a value of
say, 8j4 will format the numbers in a width of
8 characters and with 4 decimal places.
c =: % 1 + i. 2 2 
w =: 8j4 ": c 
$ w 
1 0.5
0.33333333 0.25 
1.0000 0.5000
0.3333 0.2500 
2 16 
If the width is specified as zero (as in say 0j3)
then sufficient width is allowed. If the number of decimal places
is negative (as in 10j_3) then numbers are shown in "scientific notation"
c 
0j3 ": c 
10j_3 ": c 
1 0.5
0.33333333 0.25 
1.000 0.500
0.333 0.250 
1.000e0 5.000e_1
3.333e_1 2.500e_1 
This brings us to the end of Chapter 19.
