Reputation: 2233
I am looking for a way to be able to translate between single precision and double precision. One example would be to divide 2 integers and get a floating result. How is that possible?
Upvotes: 3
Views: 2317
Reputation: 96
10 7
SWAP S>D D>F S>D D>F F/
F.
> 1.4285714 Ok
see also: http://forth.sourceforge.net/std/dpans/dpans12.htm
Upvotes: 8
Reputation: 5619
NB. rvm's answer relies on a separate floating-point stack, which - although not guaranteed by the standard - is extremely common. On kForth, a system with a unified floating-point stack and two-cell floats, you might write
: s>f s>d d>f ;
: r/ ( n n -- r ) \ 'r' for floating-point; 'f' for flags, true/false.
swap s>f rot s>f f/ ;
, which is still not standard: it relies on knowledge about how wide FP numbers are on the stack. Here are two portable methods:
: r/ ( n1 n2 -- r )
locals| n2 n1 |
n1 s>f n2 s>f f/ ;
: r/ ( n1 n2 -- r )
>r s>f r> s>f f/ ;
Although your best option is to just declare the environmental dependency and go on your way. A separate floating-point stack really helps, just about everything does it that way, and a brief prelude can implement an FP stack in software should you ever want to port your code to one of the very rare systems that presents you with a unified FP stack.
All of that aside, here is a second answer to your question: you don't need floating-point numbers to deal in fractional values (and in some cases, like money, you not only don't need them but don't want them). Forth makes it very easy for you to use fixed-precision numbers with scaling operators and custom numerical output.
An example of custom numerical output:
: .$ ( $ -- )
s>d <# # # [char] . hold #s [char] $ hold #> type ;
100 .$ \ outputs: $1.00
1525 .$ \ outputs: $15.25
An example of scaled division:
\ what's 14 divided by three, with four fractional digits of precision?
14 1000 3 */ \ result: 4666 -- use a word like .$ to display it as 4.666
(Note that n1 n2 n3 */
is more precise than n1 n2 * n3 /
-- read the spec.)
: cents ( n -- $ ) ;
: dollars ( n -- $ ) 100 * ;
: $ ( "$" -- $ )
parse-word evaluate d>s ;
\ what's 14 dollars divided by 3?
14 dollars 3 / .$ \ outputs: $4.66
\ what's 42.35 dollars divided by 2?
$ 42.35 2 / .$ \ outputs: $21.17 (note the loss of a penny!)
Two notes about that $
word. First, it has an environmental dependency on the system accepting as a double a number with a . anywhere in it, rather than just at the end. Second, it accepts numerals with a . anywhere in them, even at the end, but the numbers are still interpreted to have two fractional digits -- e.g., $ 4235.
is interpreted as 42 dollars and 35 cents, and not four-thousand two-hundred thirty-five dollars. So, it's sloppy, but you can write a parsing word that's both stricter and more portable.
You might say, "that sounds like extra work, floating-point numbers don't demand as much programmer discipline." Well, before you let that impression fossilize, read What Every Computer Science Must Know About Floating-Point Arithmetic :-)
(To sheepez's question, there's no remotely serious ANS Forth system that doesn't have floating-point number support. You may need to load the FP facilities, but they'll be there - and 'loadable' doesn't mean 'tacked on' or 'less efficient'. Consult your Forth system's docs.)
Upvotes: 7