Revision 2013-10-29
This simple floating-point output package has features found
in more comprehensive implementations yet
is remarkably compact
and portable. Based on code and algorithm from Forth Inc.
\ SFPOUT.F
\
\ Simple Floating Point Output
\
\ Main words:
\
\ (F.) (FS.) (FE.) F.R FS.R FE.R F. FS. FE.
\ FDP PLACES
\
\ This package should function correctly on any Forth
\ system with the following limitations:
\
\ - Don't attempt to output non-numbers such as NANs
\ or INFs as it will enter an infinite loop.
\ - Floating-point strings are limited to the size of
\ the system's pictured numeric output buffer.
\
\ History:
\ 131029 Fix (F.) to use FDP. Add F. FS. FE. PLACES
FORTH DEFINITIONS DECIMAL
\ Floating-point pictured numeric output operators
: <#. ( F: r1 -- r2 ) FROUND <# ;
: #. ( F: r1 -- r2 ) 10.E F/ FDUP FLOOR FSWAP FOVER F-
10.E F* FROUND F>D D>S [CHAR] 0 + HOLD ;
: #S. ( F: r1 -- r2 ) BEGIN #. FDUP F0= UNTIL ;
: #>. ( F: r -- ) ( c-addr u ) FDROP 0 0 #> ;
: SIGN. ( flag -- ) IF [CHAR] - HOLD THEN ;
\ Variable controlling trailing decimal point display.
\ Default (ON) is to always display decimal point.
VARIABLE FDP 1 FDP !
: 10^n ( r1 n -- r2 ) 0 ?DO 10.E F* LOOP ;
: #.n ( r1 n -- r2 ) 0 ?DO #. LOOP ;
VARIABLE rscale 1 rscale !
FVARIABLE rstep 10.E rstep F!
VARIABLE fdpl 4 fdpl !
\ Normalize to range 1.0 <= r < STEPSIZE
: fnorm ( r1 -- |r2| sign exp )
FDUP F0< 0 2>R FABS
FDUP F0= 0= IF
BEGIN FDUP rstep F@ F< 0=
WHILE rstep F@ F/ R> rscale @ + >R REPEAT
BEGIN FDUP 1.0E F<
WHILE rstep F@ F* R> rscale @ - >R REPEAT
THEN 2R> ;
\ Convert fixed-point
: fcvt ( r n -- )
>R FDUP F0< ( sign) R> 2>R
FABS FDP @ IF ( always output decimal point )
R> #.n [CHAR] . HOLD
ELSE ( conditionally output decimal point )
R@ #.n R> IF [CHAR] . HOLD THEN
THEN #S. R> SIGN. #>. ;
\ Convert real number r to string c-addr u in exponential
\ notation with n places right of the decimal point.
: (e.) ( r n scale step -- c-addr u )
rstep F! rscale ! 0 MAX >R fnorm
R> 2>R IF FNEGATE THEN 1.E R@ 10^n
FSWAP FOVER F* FROUND ( make integer)
FDUP FABS FROT F/ rstep F@ F< 0= IF ( overflow)
rstep F@ F/ R> R> rscale @ + >R >R THEN
<#. R> R> S>D TUCK DABS # #S 2DROP
0< IF [CHAR] - ELSE [CHAR] + THEN HOLD
[CHAR] E HOLD fcvt ;
\ Convert real number r to string c-addr u in scientific
\ notation with n places right of the decimal point.
: (FS.) ( r n -- c-addr u ) 1 10.E (e.) ;
\ Display real number r in scientific notation right-
\ justified in a field width u with n places right of
\ the decimal point.
: FS.R ( r n u -- ) >R (FS.) R> OVER - SPACES TYPE ;
\ Convert real number r to string c-addr u in engineering
\ notation with n places right of the decimal point.
: (FE.) ( r n -- c-addr u ) 3 1000.E (e.) ;
\ Display real number r in engineering notation right-
\ justified in a field width u with n places right of
\ the decimal point.
: FE.R ( r n u -- ) >R (FE.) R> OVER - SPACES TYPE ;
\ Convert real number r to string c-addr u in fixed-point
\ notation with n places right of the decimal point.
: (F.) ( r n -- c-addr u )
0 MAX DUP >R 10^n <#. ( round) R> fcvt ;
\ Display real number r in fixed-point notation right-
\ justified in a field width u with n places right of
\ the decimal point.
: F.R ( r n u -- ) >R (F.) R> OVER - SPACES TYPE ;
\ Set decimal places control for F. FS. FE.
: PLACES ( n -- ) fdpl ! ;
: F. ( r -- ) fdpl @ 0 F.R SPACE ;
: FS. ( r -- ) fdpl @ 0 FS.R SPACE ;
: FE. ( r -- ) fdpl @ 0 FE.R SPACE ;
[DEFINED] DXFORTH [IF] behead 10^n (e.) [THEN]
\ end
Top Home Forth
![]()
Page updated: 29 Oct 2013