Guides/General FAQ/Numbers and Character Representations

From J Wiki
Jump to navigation Jump to search

How to convert between numbers and character representations of numbers

Sometimes we have the character representation of a number but we want to work with number represented whereas, conversely, sometimes we wish to convert a number to characters. Representing numbers in bases other than 10 can be done using numeric or character vectors; see J Phrases for Changing Data Types

Number to Character Using Format in Newer and Older Form

Use one of the variants of the verb Format (8!:0) to convert from a number to its character equivalent:

   fmt=: 8!:0
   fmt 1 _2 3.14 4e_3
+-+--+----+-----+
|1|-2|3.14|0.004|
+-+--+----+-----+

This boxes the results. However,

   fmt2=: 8!:2
   fmt2 1 22 333 4444
1223334444

does not.

Padding with Leading Zeros

The foreign Format (8!:0) takes an optional left argument of a format string - see the details here. One common use of a format string is to pad numbers with leading zeros, e.g.

   'r<0>4.0' 8!:0 i.5
+----+----+----+----+----+
|0000|0001|0002|0003|0004|
+----+----+----+----+----+

A general function like this

lead0s=: 13 : '(]`> @. (1=[:#,))(''r<0>'',(":x),''.0'') 8!:0 y'

may also be helpful, e.g.

   3 lead0s i.5
+---+---+---+---+---+
|000|001|002|003|004|
+---+---+---+---+---+

Oleg Kobchenko recommends using take with fill {.!.'0' as the best generic method for leading zero padding:

   _3{.!.'0' &.> (8!:0) i.5
+---+---+---+---+---+
|000|001|002|003|004|
+---+---+---+---+---+

Or another yet more generic one:

  zeropad=: (-@[ {. [: ": 10&^@[ + ])"0
  5 zeropad 123 1234
00123
01234
  2 5 zeropad&.> 123 1234
+--+-----+
|23|01234|
+--+-----+

None of these methods account for negative numbers but that can be done as a separate step if required, perhaps using and adverb like this:

   leadneg=: 1 : '(u |y),~''-''#~_1=*y'
   3&zeropad leadneg"0 -i.3
000
-001
-002

   5&lead0s leadneg"0 &.> -i.3
+-----+------+------+
|00000|-00001|-00002|
+-----+------+------+

Foreign Format (8!:n)

From the Dictionary definition of the variants of this verb:

[x] 8!:0 y Format. Format array y according to format phrases x . Each formatted number is in a box.

[x] 8!:1 y Format1. As in x 8!:0 y , but y has rank at most 2 and each formatted column is in a box.

[x] 8!:2 y Format2. As in x 8!:0 y , but y has rank at most 2 and the result is a literal table.

So,

   fmt1=: 8!:1
   fmt1 i.2 3
+-+-+-+
|0|1|2|
|3|4|5|
+-+-+-+
   (8!:2) i.2 3
012
345

(Older) Number to Character (":)

For older versions of J in which 8!:n is not available, one can use the older, primitive version of Format (":) :

   ": 1 22 33.3               NB. Monad
1 22 33.3
   'Numbers: ',": 1 22 33.3   NB. Show that result is character
Numbers: 1 22 33.3

An optional left argument specifies a formatting string using complex numbers where the real part determines the length of the formatted number and the imaginary part determines the number of digits after the decimal point:

   'Formatted numbers: ',6j1": 1 22 33.3
Formatted numbers:    1.0  22.0  33.3

Format Numbers as Character, Specifying Number of Digits to Display (RjI ":)

The primitive Format also takes a complex number as the optional left argument to specify total length of the resulting string (real part) and number of digits after the decimal point (imaginary part). For example, the value of the mathematical constant "e" shown to the limits of precision (specified by 9!:10):

   ^1
2.7182818

To show more digits as a character vector:

   19j17 ": ^1
2.71828182845904510

Asking for more precision than we really have gives spurious trailing zeroes:

   29j27 ": ^1
2.718281828459045100000000000

Allowing for too few digits before (and including) the decimal point:

   16j15 ": ^1
****************

Character to Number (".)

Use the verb Numbers (".) to convert from a character string to equivalent number. For example,

   ". '1 2 35'
1 2 35

To see that the result is numeric:

   100+". '1 2 35'
101 102 135

The dyadic form of this verb may be faster and it allows a default value to be substituted for any string not convertible to a valid number:

   _99 ".&>'123';'bad';'456';'nutherbad';'789'  NB. Substitute "_99" for non-numbers
123 _99 456 _99 789

   $nn=. '0123456789   '
13
   many=. nn{~?1e7$#nn
   6!:2 '".many'       NB. Monad
2.2764244
   6!:2 '_.".many'     NB. Dyad using "indeterminate" substitution...
1.3662863
   (_.".many)-:".many
1

Converting numbers from an Excel spreadsheet has its own dangers; see caveats about numbers from Excel.

Note that the monadic form of "., called "Do", is a general verb for running a J phrase represented as a character vector, i.e.

   ". '1+2'
3
   ]randadd=. (":3?10),' + ',":3?100
0 6 9 + 48 49 29
   ". randadd
48 55 38

   NB. Random equations:
   eqn,' = ',": ". eqn=. (":?10),((]{~[:?#)'+-*%'),":?100
4%58 = 0.068965517
   eqn,' = ',": ". eqn=. (":?10),((]{~[:?#)'+-*%'),":?100
9+30 = 39
   eqn,' = ',": ". eqn=. (":?10),((]{~[:?#)'+-*%'),":?100
5*42 = 210

This is why something like this

   ". '1 -2 -3'
2

might be puzzling until you understand that it is evaluating the J expression to perform successive subtractions, equivalent to

   -/1 2 3
2

whereas the following may have been intended:

   ". '1 _2 _3'
1 _2 _3

See also the following "How to convert negative numbers..."] for this specific problem.

How to convert negative numbers between J and other applications

Negative numbers in J are preceded by the underscore character "_" whereas most applications use the dash "-" for this purpose. So, "_2" in J would be represented as "-2" in, say, Excel. A commonly-asked question is how to convert from one representation to the other.

Negative Representations to J Numbers

Typically, we use the dyadic verb Numbers (".) to convert from, e.g. -2 to _2, i.e.

   _. ". &> '-2';'1e-2'
_2 0.01

The left argument "_." is a number (Indeterminate in this case) to substitute for any non-numeric string. Indeterminate seems appropriate to use for a value we cannot figure out, but any other numeric value can be used. For example,

   12345 ". &> '-3';'nonnumeric';'3e-3';'oops';'-3e-3'
_3 12345 0.003 12345 _0.003

or

   _99.9 ". &> '-3';'nonnumeric';'3e-3';'oops';'-3e-3'
_3 _99.9 0.003 _99.9 _0.003

From J Number to Character Representation Suitable for Another Application: Underscore to Minus

Typically, we use the verb Format (8!:0) to convert from J to a more standard representation:

   fmt=: 8!:0
   fmt 1 _2 3.14 4e_3
+-+--+----+-----+
|1|-2|3.14|0.004|
+-+--+----+-----+

Notice that fmt is smart enough to box its results; this is necessary because it must convert numbers into character strings.

The older version of Format (":) doesn't do as much but works with older versions of J; see the preceding section.

If you use this older version, you have to handle the negative sign replacement separately. Something like this would work for the simplest case:

   cm=: ('_',a.)&i. { ('-',a.)"_
   cm ": -12.34
-12.34
   'A negative number: ','.',~cm ": -12.34
A negative number: -12.34.
   cm ": -i.5
0 -1 -2 -3 -4