Display of numbers and character strings

published: 24 May 2019 / updated 1 September 2020

Lire cette page en français

 

Digital base change

Also applicable on Flash Forth for Arduino

FORTH does not handle just any numbers. The ones you used while trying the previous examples are signed single precision integers. The domain of definition of single precision integers is between minus 32768 and plus 32767. Example:

32767 .         \ display    32767 
-32768 .        \ display    -32768 
65535 .         \ display    -1 (on FRTH systems with 16 bits stack) 

These numbers can be processed in any numeric base, all bases numbers between 2 and 36 being valid:

255 HEX . DECIMAL    \ display    FF 

You can choose an even larger number base, but the available symbols will come out of the alpha-numeric set [0..9, A..Z] and may become inconsistent. Example:

DECIMAL 255 BASE ! 
    ò 2 + . 

will work, but is hardly semantically conceivable.

The current numeric base is controlled by a variable named BASE and whose content can be changed. So, to switch to binary, just store the value 2 in BASE. Example:

2 BASE ! 

and type DECIMAL to return to the decimal numeric base.

Forth has two predefined words to select different digital bases:

As soon as one of these numerical bases is selected, the literal numbers will be interpreted, displayed or processed in this database. Any number previously entered in a base numeric different from the current numeric base is automatically converted in the current digital base. Example:

DECIMAL     \ decimal base 
255         \ push 255 on stack 
HEX         \ select hexadecimal base 
1+          \ increment 255 to 256 
.           \ display     100 

You can define your own numeric base by defining the appropriate word or by storing this database in BASE. Example:

: BINARY ( ---)         \ select binary base 
    2 BASE ! ; 
DECIMAL 255 BINARY .    \ display     11111111 

The contents of BASE can be stacked like the contents of any what other variable:

VARIABLE PUT_BASE       \ PUT_BASE variable definition 
BASE @ PUT_BASE !       \ BASE content storage in PUT_BASE 
HEX FF 10 + .           \ display 10F 
PUT_BASE @ BASE !       \ restore BASE with contents of PUT_BASE 

In a "colon" definition, the content of BASE can pass by the return stack:

: OPERATION ( ---) 
    BASE @ >R       \ store BASE on return stack 
    HEX FF 10 + .   \ operation of the previous example 
    R> BASE ! ;     \ restore initial value of BASE 

WARNING: the words >R and R> cannot be used in interpreted mode. You can only use these words in a definition that will be compiled.

Definition of new display formats

Also applicable on Flash Forth for Arduino

Forth has primitives allowing to adapt the display of a number to a any format. These primitives only deal with double precision numbers:

These words can only be used within a definition. Example, either to display a number expressing an amount expressed in francs with the comma as the decimal separator:

: EUROS ( ud ---) 
    <# # # ASCII , HOLD #S #> 
    TYPE ." EUR " ; 

Execution examples:

0.35  EUROS             \ display     0,35 EUR 
35.75 EUROS             \ display     35,75 EUR 
10.15 35.75 D+ EUROS    \ display     45,90 EUR 

The definition of EUROS does not take into account the sign of the result, nor the position of the decimal point. If you type:

35. EUROS          \ you will have 0.35 EUR on display 

In the definition of EUROS, the word <# begins the format definition sequence display; the two words # place the digits of units and tens in the character string; ASCII , HOLD place the character, (comma) after the two digits on the right, the word #S completes the format display with non-zero digits after "," the word #> closes the format definition and stack the address and length of the string containing the digits of the number to display; the word TYPE displays this string.

At runtime, a display format sequence deals exclusively with signed or unsigned double precision integers. The concatenation of different elements of the chain is done from right to left, i.e. starting with the least significant digits.

Number processing by display format sequence is performed according to the current digital base. The digital base can be changed between two digits.

Here is a more complex example demonstrating the compactness of FORTH. It's about write a program converting any number of seconds in the format HH: MM: SS:

: :00 ( ---) 
    DECIMAL #           \ insert digit unit in decimal 
    6 BASE !            \ base 6 selection 
    #                   \ ten digit insertion 
    ASCII : HOLD        \ character : insertion 
    DECIMAL ;           \ return to decimal base 
: HMS ( ud ---)         \ displays number seconds format HH:MM:SS 
    <# :00 :00 #S #> TYPE SPACE ; 

Execution examples:

59. HMS     \ display     0:00:59
60. HMS     \ display     0:01:00
4500. HMS   \ display     1:15:00

Explanation: the seconds and minutes display system is called the sexagesimal system. The 'units' are expressed in the base numeric decimal, 'tens' are expressed in base six. The word :00 defined previously manages the conversion of 'units' and 'tens' in these two bases for formatting digits corresponding to seconds and minutes. For the hours, the digits are all decimal.

Another example, either to define a program converting an integer simple decimal precision in binary and displaying it as bbbb bbbb bbbb bbbb:

: FOUR-DIGITS ( ---) 
    # # # # 32 HOLD ; 
: AFB ( d ---)              \ format 4 digits and a space 
    BASE @ >R               \ Current database backup 
    2 BASE !                \ Binary digital base selection 
    <# 
    4 0 DO                  \ Format Loop 
        FOUR-DIGITS 
    LOOP 
    #> TYPE SPACE           \ Binary display 
    R> BASE ! ;             \ Initial digital base restoration 

Example of execution:

DECIMAL 12. AFB    \ display     0000 0000 0000 0110 
HEX 3FC5. AFB      \ display     0011 1111 1100 0101 

Another example, or to create a telephone diary where you associate a patronymic one or more telephone numbers. We define a word by patronymic:

: .## ( ---) 
    # # ASCII . HOLD ; 
: .TEL ( d ---) 
    CR <# .## .## .## .## .## #> TYPE CR BYE ; 
: DUGENOU ( ---) 
    .0618051254 .TEL ; 

This diary, which can be compiled from a source file, is easily editable, and although the names are not sorted, the search there is extremely fast.

Display of characters and character strings

The display of a character is achieved by the word EMIT :

65 EMIT         \ display A 

Displayable characters are in the range 32..255. The codes between 0 and 31 will also be displayed, subject to certain characters executed as control codes. Here is a definition displaying the entire character set of the ASCII table:

: ASCII-SET ( ---) 
    DARK 256 32 
    DO 
        I 3 .R SPACE        \ display character code 
        I EMIT 2 SPACES     \ character poster 
        #OUT @ 77 = 
        IF 
            CR 
        THEN 
    LOOP ; 

Running ASCII-SET displays ASCII codes and characters whose code is between 32 and 255. To display the equivalent table with the ASCII codes in hexadecimal, type HEX ASCII-SET.

Character strings are displayed in various ways. The first one, usable in compilation only, displays a character string delimited by the character "(quotation mark):

: TITLE ." GENERAL MENU" ; 
TITRE    \  display     GENERAL MENU 

The string is separated from the word ." by at least one space character.

A character string can also be compiled by the word S" and delimited by the character "(quotation mark):

: LINE1 ( --- adr len) 
    S" D..Data logging" ; 

Executing LINE1 drops the address and the length of the string compiled in the definition. The display is made by the word TYPE:

LINE1 TYPE    \ display D..Data logging 

At the end of the display of a character string, the newline must be caused if desired:

LINE1 TYPE   \ display D..Data logging 
CR TITLE CR CR LINE1 TYPE CR 
\ display 
\ GENERAL MENU 
\ 
\ D..Data logging 

One or more spaces can be added at the start or end of the display of a alphanumeric string:

SPACE         \ displays a space character 
10 SPACES     \ displays 10 characters space