From 3731319e0788267b419b299d5dc96d9215aa20c4 Mon Sep 17 00:00:00 2001 From: crc Date: Sun, 22 Oct 2017 02:51:19 +0000 Subject: [PATCH] example adding support for converting strings to numbers in bases other than decimal FossilOrigin-Name: 37258feac1c8b57c3336b4586622d6a2bbe77decead532736dd835904e23c380 --- example/StringToNumberWithBase.forth | 48 ++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 example/StringToNumberWithBase.forth diff --git a/example/StringToNumberWithBase.forth b/example/StringToNumberWithBase.forth new file mode 100644 index 0000000..d001c06 --- /dev/null +++ b/example/StringToNumberWithBase.forth @@ -0,0 +1,48 @@ +A standard RETRO image only supports decimal base numbers. This +shows a way to add support for multiple bases. + +I begin by creating a variable for the current base and words to +set this to specific values quickly. + +~~~ +#10 'Base var + +:decimal #10 !Base ; +:binary #2 !Base ; +:octal #8 !Base ; +:hex #16 !Base ; +~~~ + +Next, a string constant with the symbols for each digit. Note that +I'm only going to support uppercase for hexadecimal. + +~~~ +'0123456789ABCDEF 'DIGITS s:const +~~~ + +So conversion to a numeric value is pretty easy. The basic idea +here is: + +- set a variable to hold the numeric value to zero (as a stating point) +- check to see if the first character is - for negative, set a modifier +- for each character in the string: + + - convert to a numeric value (in this case, it's the index in the + DIGITS string) + - Multiply the last value of the number accumulator by the base + - Add the converted value + - Store the result in the number accumulator + +- Multiply the final number by the modifier + +~~~ +{{ + 'Number var + 'Mod var + :convert (c-) &DIGITS swap s:index-of @Number @Base * + !Number ; + :check-sign (s-s) dup fetch $- eq? [ #-1 !Mod n:inc ] [ #1 !Mod ] choose ; +---reveal--- + :s:to-number (s-n) + #0 !Number check-sign [ convert ] s:for-each @Number @Mod * ; +}} +~~~