### Author Topic: Math Evaluator by SMcNeill  (Read 1036 times)

0 Members and 1 Guest are viewing this topic.

#### The Librarian

• Moderator
• Newbie
• Posts: 42 ##### Math Evaluator by SMcNeill
« on: March 21, 2020, 11:28:52 PM »
Math Evaluator

Author: @SMcNeill
Source: QB64.org Forum
URL: https://www.qb64.org/forum/index.php?topic=1555.0
Version: Jan 07, 2020
Tags: [qb64], [interpreter]

Description:
Here's my little math evaluation routine, which everybody's been using for ages, even if they don't know they have!  :D

If you look inside QB64.bas, you'll see these routines, which are what the IDE uses to calculate math values for use with CONST and then substitute the finished product into your code.

Source Code:
Code: QB64: [Select]
1. SCREEN _NEWIMAGE(1024, 720, 32)
2. REDIM SHARED OName(0) AS STRING 'Operation Name
3. REDIM SHARED PL(0) AS INTEGER 'Priority Level
4. REDIM SHARED PP_TypeMod(0) AS STRING, PP_ConvertedMod(0) AS STRING 'Prepass Name Conversion variables.
5.
6.     i\$ = INPUT\$(1)
7.
8.     PRINT "Formula to Evaluate => ";
9.         CASE CHR\$(8)
10.             eval\$ = LEFT\$(eval\$, LEN(eval\$) - 1)
11.         CASE CHR\$(13)
12.             eval\$ = ""
13.         CASE CHR\$(27)
14.             eval\$ = eval\$ + i\$
15.     PRINT eval\$
16.     result\$ = Evaluate_Expression(eval\$)
17.     PRINT "Result: "; result\$
18.     _CLIPBOARD\$ = eval\$ + " = " + result\$
19.
20.
21. 'Steve Subs/Functins for _MATH support with CONST
22. FUNCTION Evaluate_Expression\$ (e\$)
23.     t\$ = e\$ 'So we preserve our original data, we parse a temp copy of it
24.     PreParse t\$
25.
26.
27.     IF LEFT\$(t\$, 5) = "ERROR" THEN Evaluate_Expression\$ = t\$: EXIT FUNCTION
28.
29.     'Deal with brackets first
30.     EXP\$ = "(" + t\$ + ")" 'Starting and finishing brackets for our parse routine.
31.
32.         Eval_E = INSTR(EXP\$, ")")
33.         IF Eval_E > 0 THEN
34.             c = 0
35.             DO UNTIL Eval_E - c <= 0
36.                 c = c + 1
37.                 IF Eval_E THEN
38.                     IF MID\$(EXP\$, Eval_E - c, 1) = "(" THEN EXIT DO
39.             s = Eval_E - c + 1
40.             IF s < 1 THEN Evaluate_Expression\$ = "ERROR -- BAD () Count": EXIT SUB
41.             eval\$ = " " + MID\$(EXP\$, s, Eval_E - s) + " " 'pad with a space before and after so the parser can pick up the values properly.
42.
43.             'PRINT "Before ParseExpression: "; eval\$
44.             ParseExpression eval\$
45.             'PRINT "After ParseExpression: "; eval\$
46.             eval\$ = LTRIM\$(RTRIM\$(eval\$))
47.             IF LEFT\$(eval\$, 5) = "ERROR" THEN Evaluate_Expression\$ = eval\$: EXIT SUB
48.             EXP\$ = DWD(LEFT\$(EXP\$, s - 2) + eval\$ + MID\$(EXP\$, Eval_E + 1))
49.             'PRINT exp\$
50.             IF MID\$(EXP\$, 1, 1) = "N" THEN MID\$(EXP\$, 1) = "-"
51.
52.             'temppp\$ = DWD(LEFT\$(exp\$, s - 2) + " ## " + eval\$ + " ## " + MID\$(exp\$, e + 1))
53.     LOOP UNTIL Eval_E = 0
54.     c = 0
55.         c = c + 1
56.         SELECT CASE MID\$(EXP\$, c, 1)
57.             CASE "0" TO "9", ".", "-" 'At this point, we should only have number values left.
58.             CASE ELSE: Evaluate_Expression\$ = "ERROR - Unknown Diagnosis: (" + EXP\$ + ") ": EXIT SUB
59.     LOOP UNTIL c >= LEN(EXP\$)
60.
61.     Evaluate_Expression\$ = EXP\$
62.
63.
64.
65. SUB ParseExpression (EXP\$)
66.     DIM num(10) AS STRING
67.     'PRINT exp\$
68.     EXP\$ = DWD(EXP\$)
69.     'We should now have an expression with no () to deal with
70.     'IF MID\$(exp\$, 2, 1) = "-" THEN exp\$ = "0+" + MID\$(exp\$, 2)
71.     FOR J = 1 TO 250
72.         lowest = 0
73.         DO UNTIL lowest = LEN(EXP\$)
74.             lowest = LEN(EXP\$): OpOn = 0
75.             FOR P = 1 TO UBOUND(OName)
76.                 'Look for first valid operator
77.                 IF J = PL(P) THEN 'Priority levels match
78.                     IF LEFT\$(EXP\$, 1) = "-" THEN op = INSTR(2, EXP\$, OName(P)) ELSE op = INSTR(EXP\$, OName(P))
79.                     IF op > 0 AND op < lowest THEN lowest = op: OpOn = P
80.             IF OpOn = 0 THEN EXIT DO 'We haven't gotten to the proper PL for this OP to be processed yet.
81.             IF LEFT\$(EXP\$, 1) = "-" THEN op = INSTR(2, EXP\$, OName(OpOn)) ELSE op = INSTR(EXP\$, OName(OpOn))
82.             numset = 0
83.
84.             '*** SPECIAL OPERATION RULESETS
85.             IF OName(OpOn) = "-" THEN 'check for BOOLEAN operators before the -
86.                 SELECT CASE MID\$(EXP\$, op - 3, 3)
87.                     CASE "NOT", "XOR", "AND", "EQV", "IMP"
88.                         EXIT DO 'Not an operator, it's a negative
89.                 IF MID\$(EXP\$, op - 3, 2) = "OR" THEN EXIT DO 'Not an operator, it's a negative
90.
91.             IF op THEN
92.                 c = LEN(OName(OpOn)) - 1
93.                     SELECT CASE MID\$(EXP\$, op + c + 1, 1)
94.                         CASE "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".", "N": numset = -1 'Valid digit
95.                         CASE "-" 'We need to check if it's a minus or a negative
96.                             IF OName(OpOn) = "_PI" OR numset THEN EXIT DO
97.                         CASE ",": numset = 0
98.                         CASE ELSE 'Not a valid digit, we found our separator
99.                     c = c + 1
100.                 LOOP UNTIL op + c >= LEN(EXP\$)
101.                 e = op + c
102.
103.                 c = 0
104.                     c = c + 1
105.                     SELECT CASE MID\$(EXP\$, op - c, 1)
106.                         CASE "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".", "N" 'Valid digit
107.                         CASE "-" 'We need to check if it's a minus or a negative
108.                             c1 = c
110.                                 c1 = c1 + 1
111.                                 SELECT CASE MID\$(EXP\$, op - c1, 1)
112.                                     CASE "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "."
114.                                         EXIT DO 'It's a minus sign
115.                                         'It's a negative sign and needs to count as part of our numbers
116.                             LOOP UNTIL op - c1 <= 0
117.                             IF bad THEN EXIT DO 'We found our seperator
118.                         CASE ELSE 'Not a valid digit, we found our separator
119.                 LOOP UNTIL op - c <= 0
120.                 s = op - c
121.                 num(1) = MID\$(EXP\$, s + 1, op - s - 1) 'Get our first number
122.                 num(2) = MID\$(EXP\$, op + LEN(OName(OpOn)), e - op - LEN(OName(OpOn)) + 1) 'Get our second number
123.                 IF MID\$(num(1), 1, 1) = "N" THEN MID\$(num(1), 1) = "-"
124.                 IF MID\$(num(2), 1, 1) = "N" THEN MID\$(num(2), 1) = "-"
125.                 IF num(1) = "-" THEN
126.                     num(3) = "N" + EvaluateNumbers(OpOn, num())
127.                     num(3) = EvaluateNumbers(OpOn, num())
128.                 IF MID\$(num(3), 1, 1) = "-" THEN MID\$(num(3), 1) = "N"
129.                 'PRINT "*************"
130.                 'PRINT num(1), OName(OpOn), num(2), num(3), exp\$
131.                 IF LEFT\$(num(3), 5) = "ERROR" THEN EXP\$ = num(3): EXIT SUB
132.                 EXP\$ = LTRIM\$(N2S(DWD(LEFT\$(EXP\$, s) + RTRIM\$(LTRIM\$(num(3))) + MID\$(EXP\$, e + 1))))
133.                 'PRINT exp\$
134.             op = 0
135.
136.
137.
138.
139. SUB Set_OrderOfOperations
140.     'PL sets our priortity level. 1 is highest to 65535 for the lowest.
141.     'I used a range here so I could add in new priority levels as needed.
142.     'OName ended up becoming the name of our commands, as I modified things.... Go figure!  LOL!
143.     REDIM OName(10000) AS STRING, PL(10000) AS INTEGER
144.     'Constants get evaluated first, with a Priority Level of 1
145.
146.     i = i + 1: OName(i) = "C_UOF": PL(i) = 5 'convert to unsigned offset
147.     i = i + 1: OName(i) = "C_OF": PL(i) = 5 'convert to offset
148.     i = i + 1: OName(i) = "C_UBY": PL(i) = 5 'convert to unsigned byte
149.     i = i + 1: OName(i) = "C_BY": PL(i) = 5 'convert to byte
150.     i = i + 1: OName(i) = "C_UIN": PL(i) = 5 'convert to unsigned integer
151.     i = i + 1: OName(i) = "C_IN": PL(i) = 5 'convert to integer
152.     i = i + 1: OName(i) = "C_UIF": PL(i) = 5 'convert to unsigned int64
153.     i = i + 1: OName(i) = "C_IF": PL(i) = 5 'convert to int64
154.     i = i + 1: OName(i) = "C_ULO": PL(i) = 5 'convert to unsigned long
155.     i = i + 1: OName(i) = "C_LO": PL(i) = 5 'convert to long
156.     i = i + 1: OName(i) = "C_SI": PL(i) = 5 'convert to single
157.     i = i + 1: OName(i) = "C_FL": PL(i) = 5 'convert to float
158.     i = i + 1: OName(i) = "C_DO": PL(i) = 5 'convert to double
159.     i = i + 1: OName(i) = "C_UBI": PL(i) = 5 'convert to unsigned bit
160.     i = i + 1: OName(i) = "C_BI": PL(i) = 5 'convert to bit
161.
162.     'Then Functions with PL 10
163.     i = i + 1:: OName(i) = "_PI": PL(i) = 10
164.     i = i + 1: OName(i) = "_ACOS": PL(i) = 10
165.     i = i + 1: OName(i) = "_ASIN": PL(i) = 10
166.     i = i + 1: OName(i) = "_ARCSEC": PL(i) = 10
167.     i = i + 1: OName(i) = "_ARCCSC": PL(i) = 10
168.     i = i + 1: OName(i) = "_ARCCOT": PL(i) = 10
169.     i = i + 1: OName(i) = "_SECH": PL(i) = 10
170.     i = i + 1: OName(i) = "_CSCH": PL(i) = 10
171.     i = i + 1: OName(i) = "_COTH": PL(i) = 10
172.     i = i + 1: OName(i) = "COS": PL(i) = 10
173.     i = i + 1: OName(i) = "SIN": PL(i) = 10
174.     i = i + 1: OName(i) = "TAN": PL(i) = 10
175.     i = i + 1: OName(i) = "LOG": PL(i) = 10
176.     i = i + 1: OName(i) = "EXP": PL(i) = 10
177.     i = i + 1: OName(i) = "ATN": PL(i) = 10
178.     i = i + 1: OName(i) = "_D2R": PL(i) = 10
179.     i = i + 1: OName(i) = "_D2G": PL(i) = 10
180.     i = i + 1: OName(i) = "_R2D": PL(i) = 10
181.     i = i + 1: OName(i) = "_R2G": PL(i) = 10
182.     i = i + 1: OName(i) = "_G2D": PL(i) = 10
183.     i = i + 1: OName(i) = "_G2R": PL(i) = 10
184.     i = i + 1: OName(i) = "ABS": PL(i) = 10
185.     i = i + 1: OName(i) = "SGN": PL(i) = 10
186.     i = i + 1: OName(i) = "INT": PL(i) = 10
187.     i = i + 1: OName(i) = "_ROUND": PL(i) = 10
188.     i = i + 1: OName(i) = "_CEIL": PL(i) = 10
189.     i = i + 1: OName(i) = "FIX": PL(i) = 10
190.     i = i + 1: OName(i) = "_SEC": PL(i) = 10
191.     i = i + 1: OName(i) = "_CSC": PL(i) = 10
192.     i = i + 1: OName(i) = "_COT": PL(i) = 10
193.     i = i + 1: OName(i) = "ASC": PL(i) = 10
194.     i = i + 1: OName(i) = "CHR\$": PL(i) = 10
195.     i = i + 1: OName(i) = "C_RG": PL(i) = 10 '_RGB32 converted
196.     i = i + 1: OName(i) = "C_RA": PL(i) = 10 '_RGBA32 converted
197.     i = i + 1: OName(i) = "_RGB": PL(i) = 10
198.     i = i + 1: OName(i) = "_RGBA": PL(i) = 10
199.     i = i + 1: OName(i) = "C_RX": PL(i) = 10 '_RED32 converted
200.     i = i + 1: OName(i) = "C_GR": PL(i) = 10 ' _GREEN32 converted
201.     i = i + 1: OName(i) = "C_BL": PL(i) = 10 '_BLUE32 converted
202.     i = i + 1: OName(i) = "C_AL": PL(i) = 10 '_ALPHA32 converted
203.     i = i + 1: OName(i) = "_RED": PL(i) = 10
204.     i = i + 1: OName(i) = "_GREEN": PL(i) = 10
205.     i = i + 1: OName(i) = "_BLUE": PL(i) = 10
206.     i = i + 1: OName(i) = "_ALPHA": PL(i) = 10
207.
208.     'Exponents with PL 20
209.     i = i + 1: OName(i) = "^": PL(i) = 20
210.     i = i + 1: OName(i) = "SQR": PL(i) = 20
211.     i = i + 1: OName(i) = "ROOT": PL(i) = 20
212.     'Multiplication and Division PL 30
213.     i = i + 1: OName(i) = "*": PL(i) = 30
214.     i = i + 1: OName(i) = "/": PL(i) = 30
215.     'Integer Division PL 40
216.     i = i + 1: OName(i) = "\": PL(i) = 40
217.     'MOD PL 50
218.     i = i + 1: OName(i) = "MOD": PL(i) = 50
219.     'Addition and Subtraction PL 60
220.     i = i + 1: OName(i) = "+": PL(i) = 60
221.     i = i + 1: OName(i) = "-": PL(i) = 60
222.
223.     'Relational Operators =, >, <, <>, <=, >=   PL 70
224.     i = i + 1: OName(i) = "<>": PL(i) = 70 'These next three are just reversed symbols as an attempt to help process a common typo
225.     i = i + 1: OName(i) = "><": PL(i) = 70
226.     i = i + 1: OName(i) = "<=": PL(i) = 70
227.     i = i + 1: OName(i) = ">=": PL(i) = 70
228.     i = i + 1: OName(i) = "=<": PL(i) = 70 'I personally can never keep these things straight.  Is it < = or = <...
229.     i = i + 1: OName(i) = "=>": PL(i) = 70 'Who knows, check both!
230.     i = i + 1: OName(i) = ">": PL(i) = 70
231.     i = i + 1: OName(i) = "<": PL(i) = 70
232.     i = i + 1: OName(i) = "=": PL(i) = 70
233.     'Logical Operations PL 80+
234.     i = i + 1: OName(i) = "NOT": PL(i) = 80
235.     i = i + 1: OName(i) = "AND": PL(i) = 90
236.     i = i + 1: OName(i) = "OR": PL(i) = 100
237.     i = i + 1: OName(i) = "XOR": PL(i) = 110
238.     i = i + 1: OName(i) = "EQV": PL(i) = 120
239.     i = i + 1: OName(i) = "IMP": PL(i) = 130
240.     i = i + 1: OName(i) = ",": PL(i) = 1000
241.
242.     REDIM _PRESERVE OName(i) AS STRING, PL(i) AS INTEGER
243.
244. FUNCTION EvaluateNumbers\$ (p, num() AS STRING)
245.     DIM n1 AS _FLOAT, n2 AS _FLOAT, n3 AS _FLOAT
246.     'PRINT "EVALNUM:"; OName(p), num(1), num(2)
247.     IF INSTR(num(1), ",") THEN
248.         EvaluateNumbers\$ = "ERROR - Invalid comma (" + num(1) + ")": EXIT FUNCTION
249.     l2 = INSTR(num(2), ",")
250.     IF l2 THEN
251.         SELECT CASE OName(p) 'only certain commands should pass a comma value
252.             CASE "C_RG", "C_RA", "_RGB", "_RGBA", "_RED", "_GREEN", "C_BL", "_ALPHA"
253.                 C\$ = MID\$(num(2), l2)
254.                 num(2) = LEFT\$(num(2), l2 - 1)
255.
256.     SELECT CASE PL(p) 'divide up the work so we want do as much case checking
257.         CASE 5 'Type conversions
258.             'Note, these are special cases and work with the number BEFORE the command and not after
259.             SELECT CASE OName(p) 'Depending on our operator..
260.                 CASE "C_UOF": n1~%& = VAL(num(1)): EvaluateNumbers\$ = RTRIM\$(LTRIM\$(STR\$(n1~%&)))
261.                 CASE "C_ULO": n1%& = VAL(num(1)): EvaluateNumbers\$ = RTRIM\$(LTRIM\$(STR\$(n1%&)))
262.                 CASE "C_UBY": n1~%% = VAL(num(1)): EvaluateNumbers\$ = RTRIM\$(LTRIM\$(STR\$(n1~%%)))
263.                 CASE "C_UIN": n1~% = VAL(num(1)): EvaluateNumbers\$ = RTRIM\$(LTRIM\$(STR\$(n1~%)))
264.                 CASE "C_BY": n1%% = VAL(num(1)): EvaluateNumbers\$ = RTRIM\$(LTRIM\$(STR\$(n1%%)))
265.                 CASE "C_IN": n1% = VAL(num(1)): EvaluateNumbers\$ = RTRIM\$(LTRIM\$(STR\$(n1%)))
266.                 CASE "C_UIF": n1~&& = VAL(num(1)): EvaluateNumbers\$ = RTRIM\$(LTRIM\$(STR\$(n1~&&)))
267.                 CASE "C_OF": n1~& = VAL(num(1)): EvaluateNumbers\$ = RTRIM\$(LTRIM\$(STR\$(n1~&)))
268.                 CASE "C_IF": n1&& = VAL(num(1)): EvaluateNumbers\$ = RTRIM\$(LTRIM\$(STR\$(n1&&)))
269.                 CASE "C_LO": n1& = VAL(num(1)): EvaluateNumbers\$ = RTRIM\$(LTRIM\$(STR\$(n1&)))
270.                 CASE "C_UBI": n1~` = VAL(num(1)): EvaluateNumbers\$ = RTRIM\$(LTRIM\$(STR\$(n1~`)))
271.                 CASE "C_BI": n1` = VAL(num(1)): EvaluateNumbers\$ = RTRIM\$(LTRIM\$(STR\$(n1`)))
272.                 CASE "C_FL": n1## = VAL(num(1)): EvaluateNumbers\$ = RTRIM\$(LTRIM\$(STR\$(n1##)))
273.                 CASE "C_DO": n1# = VAL(num(1)): EvaluateNumbers\$ = RTRIM\$(LTRIM\$(STR\$(n1#)))
274.                 CASE "C_SI": n1! = VAL(num(1)): EvaluateNumbers\$ = RTRIM\$(LTRIM\$(STR\$(n1!)))
275.         CASE 10 'functions
276.             SELECT CASE OName(p) 'Depending on our operator..
277.                 CASE "_PI"
278.                     n1 = 3.14159265358979323846264338327950288## 'Future compatable in case something ever stores extra digits for PI
279.                     IF num(2) <> "" THEN n1 = n1 * VAL(num(2))
280.                 CASE "_ACOS": n1 = _ACOS(VAL(num(2)))
281.                 CASE "_ASIN": n1 = _ASIN(VAL(num(2)))
282.                 CASE "_ARCSEC": n1 = _ARCSEC(VAL(num(2)))
283.                 CASE "_ARCCSC": n1 = _ARCCSC(VAL(num(2)))
284.                 CASE "_ARCCOT": n1 = _ARCCOT(VAL(num(2)))
285.                 CASE "_SECH": n1 = _SECH(VAL(num(2)))
286.                 CASE "_CSCH": n1 = _CSCH(VAL(num(2)))
287.                 CASE "_COTH": n1 = _COTH(VAL(num(2)))
288.                 CASE "C_RG"
289.                     n\$ = num(2)
290.                     IF n\$ = "" THEN EvaluateNumbers\$ = "ERROR - Invalid null _RGB32": EXIT FUNCTION
291.                     c1 = INSTR(n\$, ",")
292.                     IF c1 THEN c2 = INSTR(c1 + 1, n\$, ",")
293.                     IF c2 THEN c3 = INSTR(c2 + 1, n\$, ",")
294.                     IF c3 THEN c4 = INSTR(c3 + 1, n\$, ",")
295.                     IF c1 = 0 THEN 'there's no comma in the command to parse.  It's a grayscale value
296.                         n = VAL(num(2))
297.                         n1 = _RGB32(n, n, n)
298.                     ELSEIF c2 = 0 THEN 'there's one comma and not 2.  It's grayscale with alpha.
299.                         n = VAL(LEFT\$(num(2), c1))
300.                         n2 = VAL(MID\$(num(2), c1 + 1))
301.                         n1 = _RGBA32(n, n, n, n2)
302.                     ELSEIF c3 = 0 THEN 'there's two commas.  It's _RGB values
303.                         n = VAL(LEFT\$(num(2), c1))
304.                         n2 = VAL(MID\$(num(2), c1 + 1))
305.                         n3 = VAL(MID\$(num(2), c2 + 1))
306.                         n1 = _RGB32(n, n2, n3)
307.                     ELSEIF c4 = 0 THEN 'there's three commas.  It's _RGBA values
308.                         n = VAL(LEFT\$(num(2), c1))
309.                         n2 = VAL(MID\$(num(2), c1 + 1))
310.                         n3 = VAL(MID\$(num(2), c2 + 1))
311.                         n4 = VAL(MID\$(num(2), c3 + 1))
312.                         n1 = _RGBA32(n, n2, n3, n4)
313.                     ELSE 'we have more than three commas.  I have no idea WTH type of values got passed here!
314.                         EvaluateNumbers\$ = "ERROR - Invalid comma count (" + num(2) + ")": EXIT FUNCTION
315.                 CASE "C_RA"
316.                     n\$ = num(2)
317.                     IF n\$ = "" THEN EvaluateNumbers\$ = "ERROR - Invalid null _RGBA32": EXIT FUNCTION
318.                     c1 = INSTR(n\$, ",")
319.                     IF c1 THEN c2 = INSTR(c1 + 1, n\$, ",")
320.                     IF c2 THEN c3 = INSTR(c2 + 1, n\$, ",")
321.                     IF c3 THEN c4 = INSTR(c3 + 1, n\$, ",")
322.                     IF c3 = 0 OR c4 <> 0 THEN EvaluateNumbers\$ = "ERROR - Invalid comma count (" + num(2) + ")": EXIT FUNCTION
323.                     'we have to have 3 commas; not more, not less.
324.                     n = VAL(LEFT\$(num(2), c1))
325.                     n2 = VAL(MID\$(num(2), c1 + 1))
326.                     n3 = VAL(MID\$(num(2), c2 + 1))
327.                     n4 = VAL(MID\$(num(2), c3 + 1))
328.                     n1 = _RGBA32(n, n2, n3, n4)
329.                 CASE "_RGB"
330.                     n\$ = num(2)
331.                     IF n\$ = "" THEN EvaluateNumbers\$ = "ERROR - Invalid null _RGB": EXIT FUNCTION
332.                     c1 = INSTR(n\$, ",")
333.                     IF c1 THEN c2 = INSTR(c1 + 1, n\$, ",")
334.                     IF c2 THEN c3 = INSTR(c2 + 1, n\$, ",")
335.                     IF c3 THEN c4 = INSTR(c3 + 1, n\$, ",")
336.                     IF c3 = 0 OR c4 <> 0 THEN EvaluateNumbers\$ = "ERROR - Invalid comma count (" + num(2) + "). _RGB requires 4 parameters for Red, Green, Blue, ScreenMode.": EXIT FUNCTION
337.                     'we have to have 3 commas; not more, not less.
338.                     n = VAL(LEFT\$(num(2), c1))
339.                     n2 = VAL(MID\$(num(2), c1 + 1))
340.                     n3 = VAL(MID\$(num(2), c2 + 1))
341.                     n4 = VAL(MID\$(num(2), c3 + 1))
342.                         CASE 0 TO 2, 7 TO 13, 256, 32 'these are the good screen values
343.                             EvaluateNumbers\$ = "ERROR - Invalid Screen Mode (" + STR\$(n4) + ")": EXIT FUNCTION
344.                     t = _NEWIMAGE(1, 1, n4)
345.                     n1 = _RGB(n, n2, n3, t)
346.                 CASE "_RGBA"
347.                     n\$ = num(2)
348.                     IF n\$ = "" THEN EvaluateNumbers\$ = "ERROR - Invalid null _RGBA": EXIT FUNCTION
349.                     c1 = INSTR(n\$, ",")
350.                     IF c1 THEN c2 = INSTR(c1 + 1, n\$, ",")
351.                     IF c2 THEN c3 = INSTR(c2 + 1, n\$, ",")
352.                     IF c3 THEN c4 = INSTR(c3 + 1, n\$, ",")
353.                     IF c4 THEN c5 = INSTR(c4 + 1, n\$, ",")
354.                     IF c4 = 0 OR c5 <> 0 THEN EvaluateNumbers\$ = "ERROR - Invalid comma count (" + num(2) + "). _RGBA requires 5 parameters for Red, Green, Blue, Alpha, ScreenMode.": EXIT FUNCTION
355.                     'we have to have 4 commas; not more, not less.
356.                     n = VAL(LEFT\$(num(2), c1))
357.                     n2 = VAL(MID\$(num(2), c1 + 1))
358.                     n3 = VAL(MID\$(num(2), c2 + 1))
359.                     n4 = VAL(MID\$(num(2), c3 + 1))
360.                     n5 = VAL(MID\$(num(2), c4 + 1))
361.                         CASE 0 TO 2, 7 TO 13, 256, 32 'these are the good screen values
362.                             EvaluateNumbers\$ = "ERROR - Invalid Screen Mode (" + STR\$(n5) + ")": EXIT FUNCTION
363.                     t = _NEWIMAGE(1, 1, n5)
364.                     n1 = _RGBA(n, n2, n3, n4, t)
365.                 CASE "_RED", "_GREEN", "_BLUE", "_ALPHA"
366.                     n\$ = num(2)
367.                     IF n\$ = "" THEN EvaluateNumbers\$ = "ERROR - Invalid null " + OName(p): EXIT FUNCTION
368.                     c1 = INSTR(n\$, ",")
369.                     IF c1 = 0 THEN EvaluateNumbers\$ = "ERROR - " + OName(p) + " requires 2 parameters for Color, ScreenMode.": EXIT FUNCTION
370.                     IF c1 THEN c2 = INSTR(c1 + 1, n\$, ",")
371.                     IF c2 THEN EvaluateNumbers\$ = "ERROR - " + OName(p) + " requires 2 parameters for Color, ScreenMode.": EXIT FUNCTION
372.                     n = VAL(LEFT\$(num(2), c1))
373.                     n2 = VAL(MID\$(num(2), c1 + 1))
374.                         CASE 0 TO 2, 7 TO 13, 256, 32 'these are the good screen values
375.                             EvaluateNumbers\$ = "ERROR - Invalid Screen Mode (" + STR\$(n2) + ")": EXIT FUNCTION
376.                     t = _NEWIMAGE(1, 1, n4)
377.                     SELECT CASE OName(p)
378.                         CASE "_RED": n1 = _RED(n, t)
379.                         CASE "_BLUE": n1 = _BLUE(n, t)
380.                         CASE "_GREEN": n1 = _GREEN(n, t)
381.                         CASE "_ALPHA": n1 = _ALPHA(n, t)
382.                 CASE "C_RX", "C_GR", "C_BL", "C_AL"
383.                     n\$ = num(2)
384.                     IF n\$ = "" THEN EvaluateNumbers\$ = "ERROR - Invalid null " + OName(p): EXIT FUNCTION
385.                     n = VAL(num(2))
386.                     SELECT CASE OName(p)
387.                         CASE "C_RX": n1 = _RED32(n)
388.                         CASE "C_BL": n1 = _BLUE32(n)
389.                         CASE "C_GR": n1 = _GREEN32(n)
390.                         CASE "C_AL": n1 = _ALPHA32(n)
391.                 CASE "COS": n1 = COS(VAL(num(2)))
392.                 CASE "SIN": n1 = SIN(VAL(num(2)))
393.                 CASE "TAN": n1 = TAN(VAL(num(2)))
394.                 CASE "LOG": n1 = LOG(VAL(num(2)))
395.                 CASE "EXP": n1 = EXP(VAL(num(2)))
396.                 CASE "ATN": n1 = ATN(VAL(num(2)))
397.                 CASE "_D2R": n1 = 0.0174532925 * (VAL(num(2)))
398.                 CASE "_D2G": n1 = 1.1111111111 * (VAL(num(2)))
399.                 CASE "_R2D": n1 = 57.2957795 * (VAL(num(2)))
400.                 CASE "_R2G": n1 = 0.015707963 * (VAL(num(2)))
401.                 CASE "_G2D": n1 = 0.9 * (VAL(num(2)))
402.                 CASE "_G2R": n1 = 63.661977237 * (VAL(num(2)))
403.                 CASE "ABS": n1 = ABS(VAL(num(2)))
404.                 CASE "SGN": n1 = SGN(VAL(num(2)))
405.                 CASE "INT": n1 = INT(VAL(num(2)))
406.                 CASE "_ROUND": n1 = _ROUND(VAL(num(2)))
407.                 CASE "_CEIL": n1 = _CEIL(VAL(num(2)))
408.                 CASE "FIX": n1 = FIX(VAL(num(2)))
409.                 CASE "_SEC": n1 = _SEC(VAL(num(2)))
410.                 CASE "_CSC": n1 = _CSC(VAL(num(2)))
411.                 CASE "_COT": n1 = _COT(VAL(num(2)))
412.         CASE 20 TO 60 'Math Operators
413.             SELECT CASE OName(p) 'Depending on our operator..
414.                 CASE "^": n1 = VAL(num(1)) ^ VAL(num(2))
415.                 CASE "SQR": n1 = SQR(VAL(num(2)))
416.                 CASE "ROOT"
417.                     n1 = VAL(num(1)): n2 = VAL(num(2))
418.                     IF n2 = 1 THEN EvaluateNumbers\$ = RTRIM\$(LTRIM\$(STR\$(n1))): EXIT FUNCTION
419.                     IF n1 < 0 AND n2 >= 1 THEN sign = -1: n1 = -n1 ELSE sign = 1
420.                     n3 = 1## / n2
421.                     IF n3 <> INT(n3) AND n2 < 1 THEN sign = SGN(n1): n1 = ABS(n1)
422.                     n1 = sign * (n1 ^ n3)
423.                 CASE "*": n1 = VAL(num(1)) * VAL(num(2))
424.                 CASE "/": n1 = VAL(num(1)) / VAL(num(2))
425.                 CASE "\"
426.                     IF VAL(num(2)) <> 0 THEN
427.                         n1 = VAL(num(1)) \ VAL(num(2))
428.                         EvaluateNumbers\$ = "ERROR - Bad operation (We shouldn't see this)"
429.                 CASE "MOD": n1 = VAL(num(1)) MOD VAL(num(2))
430.                 CASE "+": n1 = VAL(num(1)) + VAL(num(2))
431.                 CASE "-":
432.                     n1 = VAL(num(1)) - VAL(num(2))
433.         CASE 70 'Relational Operators =, >, <, <>, <=, >=
434.             SELECT CASE OName(p) 'Depending on our operator..
435.                 CASE "=": n1 = VAL(num(1)) = VAL(num(2))
436.                 CASE ">": n1 = VAL(num(1)) > VAL(num(2))
437.                 CASE "<": n1 = VAL(num(1)) < VAL(num(2))
438.                 CASE "<>", "><": n1 = VAL(num(1)) <> VAL(num(2))
439.                 CASE "<=", "=<": n1 = VAL(num(1)) <= VAL(num(2))
440.                 CASE ">=", "=>": n1 = VAL(num(1)) >= VAL(num(2))
441.         CASE ELSE 'a value we haven't processed elsewhere
442.             SELECT CASE OName(p) 'Depending on our operator..
443.                 CASE "NOT": n1 = NOT VAL(num(2))
444.                 CASE "AND": n1 = VAL(num(1)) AND VAL(num(2))
445.                 CASE "OR": n1 = VAL(num(1)) OR VAL(num(2))
446.                 CASE "XOR": n1 = VAL(num(1)) XOR VAL(num(2))
447.                 CASE "EQV": n1 = VAL(num(1)) EQV VAL(num(2))
448.                 CASE "IMP": n1 = VAL(num(1)) IMP VAL(num(2))
449.
450.     EvaluateNumbers\$ = RTRIM\$(LTRIM\$(STR\$(n1))) + C\$
451.
452.     'PRINT "AFTEREVN:"; EvaluateNumbers\$
453.
454. FUNCTION DWD\$ (EXP\$) 'Deal With Duplicates
455.     'To deal with duplicate operators in our code.
456.     'Such as --  becomes a +
457.     '++ becomes a +
458.     '+- becomes a -
459.     '-+ becomes a -
460.     t\$ = EXP\$
462.             l = INSTR(t\$, "++")
463.             IF l THEN t\$ = LEFT\$(t\$, l - 1) + "+" + MID\$(t\$, l + 2): bad = -1
464.         LOOP UNTIL l = 0
465.             l = INSTR(t\$, "+-")
466.             IF l THEN t\$ = LEFT\$(t\$, l - 1) + "-" + MID\$(t\$, l + 2): bad = -1
467.         LOOP UNTIL l = 0
468.             l = INSTR(t\$, "-+")
469.             IF l THEN t\$ = LEFT\$(t\$, l - 1) + "-" + MID\$(t\$, l + 2): bad = -1
470.         LOOP UNTIL l = 0
471.             l = INSTR(t\$, "--")
472.             IF l THEN t\$ = LEFT\$(t\$, l - 1) + "+" + MID\$(t\$, l + 2): bad = -1
473.         LOOP UNTIL l = 0
474.         'PRINT "FIXING: "; t\$
476.     DWD\$ = t\$
477.
478. SUB PreParse (e\$)
479.
480.     IF PP_TypeMod(0) = "" THEN
481.         REDIM PP_TypeMod(100) AS STRING, PP_ConvertedMod(100) AS STRING 'Large enough to hold all values to begin with
482.         PP_TypeMod(0) = "Initialized" 'Set so we don't do this section over and over, as we keep the values in shared memory.
483.         Set_OrderOfOperations 'Call this once to set up our proper order of operations and variable list
484.         'and the below is a conversion list so symbols don't get cross confused.
485.         i = i + 1: PP_TypeMod(i) = "~`": PP_ConvertedMod(i) = "C_UBI" 'unsigned bit
486.         i = i + 1: PP_TypeMod(i) = "~%%": PP_ConvertedMod(i) = "C_UBY" 'unsigned byte
487.         i = i + 1: PP_TypeMod(i) = "~%&": PP_ConvertedMod(i) = "C_UOF" 'unsigned offset
488.         i = i + 1: PP_TypeMod(i) = "~%": PP_ConvertedMod(i) = "C_UIN" 'unsigned integer
489.         i = i + 1: PP_TypeMod(i) = "~&&": PP_ConvertedMod(i) = "C_UIF" 'unsigned integer64
490.         i = i + 1: PP_TypeMod(i) = "~&": PP_ConvertedMod(i) = "C_ULO" 'unsigned long
491.         i = i + 1: PP_TypeMod(i) = "`": PP_ConvertedMod(i) = "C_BI" 'bit
492.         i = i + 1: PP_TypeMod(i) = "%%": PP_ConvertedMod(i) = "C_BY" 'byte
493.         i = i + 1: PP_TypeMod(i) = "%&": PP_ConvertedMod(i) = "C_OF" 'offset
494.         i = i + 1: PP_TypeMod(i) = "%": PP_ConvertedMod(i) = "C_IN" 'integer
495.         i = i + 1: PP_TypeMod(i) = "&&": PP_ConvertedMod(i) = "C_IF" 'integer64
496.         i = i + 1: PP_TypeMod(i) = "&": PP_ConvertedMod(i) = "C_LO" 'long
497.         i = i + 1: PP_TypeMod(i) = "!": PP_ConvertedMod(i) = "C_SI" 'single
498.         i = i + 1: PP_TypeMod(i) = "##": PP_ConvertedMod(i) = "C_FL" 'float
499.         i = i + 1: PP_TypeMod(i) = "#": PP_ConvertedMod(i) = "C_DO" 'double
500.         i = i + 1: PP_TypeMod(i) = "_RGB32": PP_ConvertedMod(i) = "C_RG" 'rgb32
501.         i = i + 1: PP_TypeMod(i) = "_RGBA32": PP_ConvertedMod(i) = "C_RA" 'rgba32
502.         i = i + 1: PP_TypeMod(i) = "_RED32": PP_ConvertedMod(i) = "C_RX" 'red32
503.         i = i + 1: PP_TypeMod(i) = "_GREEN32": PP_ConvertedMod(i) = "C_GR" 'green32
504.         i = i + 1: PP_TypeMod(i) = "_BLUE32": PP_ConvertedMod(i) = "C_BL" 'blue32
505.         i = i + 1: PP_TypeMod(i) = "_ALPHA32": PP_ConvertedMod(i) = "C_AL" 'alpha32
506.         REDIM _PRESERVE PP_TypeMod(i) AS STRING, PP_ConvertedMod(i) AS STRING 'And then resized to just contain the necessary space in memory
507.     t\$ = e\$
508.
509.     'First strip all spaces
510.     t\$ = ""
511.     FOR i = 1 TO LEN(e\$)
512.         IF MID\$(e\$, i, 1) <> " " THEN t\$ = t\$ + MID\$(e\$, i, 1)
513.
514.     t\$ = UCASE\$(t\$)
515.     IF t\$ = "" THEN e\$ = "ERROR -- NULL string; nothing to evaluate": EXIT SUB
516.
517.     'ERROR CHECK by counting our brackets
518.     l = 0
519.         l = INSTR(l + 1, t\$, "("): IF l THEN c = c + 1
520.     LOOP UNTIL l = 0
521.     l = 0
522.         l = INSTR(l + 1, t\$, ")"): IF l THEN c1 = c1 + 1
523.     LOOP UNTIL l = 0
524.     IF c <> c1 THEN e\$ = "ERROR -- Bad Parenthesis:" + STR\$(c) + "( vs" + STR\$(c1) + ")": EXIT SUB
525.
526.     'Modify so that NOT will process properly
527.     l = 0
528.         l = INSTR(l + 1, t\$, "NOT")
529.             'We need to work magic on the statement so it looks pretty.
530.             ' 1 + NOT 2 + 1 is actually processed as 1 + (NOT 2 + 1)
531.             'Look for something not proper
532.             l1 = INSTR(l + 1, t\$, "AND")
533.             IF l1 = 0 OR (INSTR(l + 1, t\$, "OR") > 0 AND INSTR(l + 1, t\$, "OR") < l1) THEN l1 = INSTR(l + 1, t\$, "OR")
534.             IF l1 = 0 OR (INSTR(l + 1, t\$, "XOR") > 0 AND INSTR(l + 1, t\$, "XOR") < l1) THEN l1 = INSTR(l + 1, t\$, "XOR")
535.             IF l1 = 0 OR (INSTR(l + 1, t\$, "EQV") > 0 AND INSTR(l + 1, t\$, "EQV") < l1) THEN l1 = INSTR(l + 1, t\$, "EQV")
536.             IF l1 = 0 OR (INSTR(l + 1, t\$, "IMP") > 0 AND INSTR(l + 1, t\$, "IMP") < l1) THEN l1 = INSTR(l + 1, t\$, "IMP")
537.             IF l1 = 0 THEN l1 = LEN(t\$) + 1
538.             t\$ = LEFT\$(t\$, l - 1) + "(" + MID\$(t\$, l, l1 - l) + ")" + MID\$(t\$, l + l1 - l)
539.             l = l + 3
540.             'PRINT t\$
541.     LOOP UNTIL l = 0
542.
543.     FOR j = 1 TO UBOUND(PP_TypeMod)
544.         l = 0
545.             l = INSTR(l + 1, t\$, PP_TypeMod(j))
546.             IF l = 0 THEN EXIT DO
547.             i = 0: l1 = 0: l2 = 0: lo = LEN(PP_TypeMod(j))
548.                 IF PL(i) > 10 THEN
549.                     l2 = _INSTRREV(l, t\$, OName\$(i))
550.                     IF l2 > 0 AND l2 > l1 THEN l1 = l2
551.                 i = i + lo
552.             LOOP UNTIL i > UBOUND(PL)
553.             'PRINT "L1:"; l1; "L"; l
554.             l\$ = LEFT\$(t\$, l1)
555.             m\$ = MID\$(t\$, l1 + 1, l - l1 - 1)
556.             r\$ = PP_ConvertedMod(j) + MID\$(t\$, l + lo)
557.             'PRINT "Y\$: "; TypeMod(j)
558.             'PRINT "L\$: "; l\$
559.             'PRINT "M\$: "; m\$
560.             'PRINT "R\$: "; r\$
561.             IF j > 15 THEN
562.                 t\$ = l\$ + m\$ + r\$ 'replacement routine for commands which might get confused with others, like _RGB and _RGB32
563.                 'the first 15 commands need to properly place the parenthesis around the value we want to convert.
564.                 t\$ = l\$ + "(" + m\$ + ")" + r\$
565.             'PRINT "T\$: "; t\$
566.             l = l + 2 + LEN(PP_TypeMod(j)) 'move forward from the length of the symbol we checked + the new "(" and  ")"
567.     '    PRINT "HERE: "; t\$
568.
569.
570.
571.     'Check for bad operators before a ( bracket
572.     l = 0
573.         l = INSTR(l + 1, t\$, "(")
574.         IF l AND l > 2 THEN 'Don't check the starting bracket; there's nothing before it.
575.             good = 0
576.             'PRINT "BEFORE: "; t\$; l
577.             FOR i = 1 TO UBOUND(OName)
578.                 m\$ = MID\$(t\$, l - LEN(OName(i)), LEN(OName(i)))
579.                 'IF OName(i) = "C_SI" THEN PRINT "CONVERT TO SINGLE", m\$
580.                 IF m\$ = OName(i) THEN good = -1: EXIT FOR 'We found an operator after our ), and it's not a CONST (like PI)
581.             'PRINT t\$; l
582.             IF NOT good THEN e\$ = "ERROR - Improper operations before (.": EXIT SUB
583.             l = l + 1
584.     LOOP UNTIL l = 0
585.
586.     'Check for bad operators after a ) bracket
587.     l = 0
588.         l = INSTR(l + 1, t\$, ")")
589.         IF l AND l < LEN(t\$) THEN
590.             good = 0
591.             FOR i = 1 TO UBOUND(oname)
592.                 m\$ = MID\$(t\$, l + 1, LEN(OName(i)))
593.                 IF m\$ = OName(i) THEN good = -1: EXIT FOR 'We found an operator after our ), and it's not a CONST (like PI
594.             IF MID\$(t\$, l + 1, 1) = ")" THEN good = -1
595.             IF NOT good THEN e\$ = "ERROR - Improper operations after ).": EXIT SUB
596.             l = l + 1
597.     LOOP UNTIL l = 0 OR l = LEN(t\$) 'last symbol is a bracket
598.
599.     'Turn all &H (hex) numbers into decimal values for the program to process properly
600.     l = 0
601.         l = INSTR(t\$, "&H")
602.             E = l + 1: finished = 0
603.                 E = E + 1
604.                 comp\$ = MID\$(t\$, E, 1)
605.                 SELECT CASE comp\$
606.                     CASE "0" TO "9", "A" TO "F" 'All is good, our next digit is a number, continue to add to the hex\$
607.                         good = 0
608.                         FOR i = 1 TO UBOUND(oname)
609.                             IF MID\$(t\$, E, LEN(OName(i))) = OName(i) AND PL(i) > 1 AND PL(i) <= 250 THEN good = -1: EXIT FOR 'We found an operator after our ), and it's not a CONST (like PI)
610.                         IF NOT good THEN e\$ = "ERROR - Improper &H value. (" + comp\$ + ")": EXIT SUB
611.                         E = E - 1
612.                         finished = -1
613.             LOOP UNTIL finished OR E = LEN(t\$)
614.             t\$ = LEFT\$(t\$, l - 1) + LTRIM\$(RTRIM\$(STR\$(VAL(MID\$(t\$, l, E - l + 1))))) + MID\$(t\$, E + 1)
615.     LOOP UNTIL l = 0
616.
617.     'Turn all &B (binary) numbers into decimal values for the program to process properly
618.     l = 0
619.         l = INSTR(t\$, "&B")
620.             E = l + 1: finished = 0
621.                 E = E + 1
622.                 comp\$ = MID\$(t\$, E, 1)
623.                 SELECT CASE comp\$
624.                     CASE "0", "1" 'All is good, our next digit is a number, continue to add to the hex\$
625.                         good = 0
626.                         FOR i = 1 TO UBOUND(oname)
627.                             IF MID\$(t\$, E, LEN(OName(i))) = OName(i) AND PL(i) > 1 AND PL(i) <= 250 THEN good = -1: EXIT FOR 'We found an operator after our ), and it's not a CONST (like PI)
628.                         IF NOT good THEN e\$ = "ERROR - Improper &B value. (" + comp\$ + ")": EXIT SUB
629.                         E = E - 1
630.                         finished = -1
631.             LOOP UNTIL finished OR E = LEN(t\$)
632.             bin\$ = MID\$(t\$, l + 2, E - l - 1)
633.             FOR i = 1 TO LEN(bin\$)
634.                 IF MID\$(bin\$, i, 1) = "1" THEN f = f + 2 ^ (LEN(bin\$) - i)
635.             t\$ = LEFT\$(t\$, l - 1) + LTRIM\$(RTRIM\$(STR\$(f))) + MID\$(t\$, E + 1)
636.     LOOP UNTIL l = 0
637.
638.     'PRINT "ALMOST:"; t\$
639.
640.     t\$ = N2S(t\$)
641.     'PRINT "ALMOST2:"; t\$
642.     VerifyString t\$
643.     'PRINT "Out of PreParse: "; e\$
644.     e\$ = t\$
645.
646.
647.
648. SUB VerifyString (t\$)
649.     'ERROR CHECK for unrecognized operations
650.     j = 1
651.         comp\$ = MID\$(t\$, j, 1)
652.         SELECT CASE comp\$
653.             CASE "0" TO "9", ".", "(", ")", ",": j = j + 1
654.                 good = 0
655.                 FOR i = 1 TO UBOUND(OName)
656.                     IF MID\$(t\$, j, LEN(OName(i))) = OName(i) THEN good = -1: EXIT FOR 'We found an operator after our ), and it's not a CONST (like PI)
657.                 IF NOT good THEN t\$ = "ERROR - Bad Operational value. (" + comp\$ + ")": EXIT SUB
658.                 j = j + LEN(OName(i))
659.     LOOP UNTIL j > LEN(t\$)
660.
661. FUNCTION N2S\$ (EXP\$) 'scientific Notation to String
662.
663.     'PRINT "Before notation:"; exp\$
664.
665.     t\$ = LTRIM\$(RTRIM\$(EXP\$))
666.     IF LEFT\$(t\$, 1) = "-" OR LEFT\$(t\$, 1) = "N" THEN sign\$ = "-": t\$ = MID\$(t\$, 2)
667.
668.     dp = INSTR(t\$, "D+"): dm = INSTR(t\$, "D-")
669.     ep = INSTR(t\$, "E+"): em = INSTR(t\$, "E-")
670.     check1 = SGN(dp) + SGN(dm) + SGN(ep) + SGN(em)
671.     IF check1 < 1 OR check1 > 1 THEN N2S = EXP\$: EXIT SUB 'If no scientic notation is found, or if we find more than 1 type, it's not SN!
672.
673.     SELECT CASE l 'l now tells us where the SN starts at.
674.         CASE IS < dp: l = dp
675.         CASE IS < dm: l = dm
676.         CASE IS < ep: l = ep
677.         CASE IS < em: l = em
678.
679.     l\$ = LEFT\$(t\$, l - 1) 'The left of the SN
680.     r\$ = MID\$(t\$, l + 1): r&& = VAL(r\$) 'The right of the SN, turned into a workable long
681.
682.
683.     IF INSTR(l\$, ".") THEN 'Location of the decimal, if any
684.         IF r&& > 0 THEN
685.             r&& = r&& - LEN(l\$) + 2
686.             r&& = r&& + 1
687.         l\$ = LEFT\$(l\$, 1) + MID\$(l\$, 3)
688.
689.     SELECT CASE r&&
690.         CASE 0 'what the heck? We solved it already?
691.             'l\$ = l\$
692.         CASE IS < 0
693.             FOR i = 1 TO -r&&
694.                 l\$ = "0" + l\$
695.             l\$ = "0." + l\$
696.             FOR i = 1 TO r&&
697.                 l\$ = l\$ + "0"
698.
699.     N2S\$ = sign\$ + l\$
700.     'PRINT "After notation:"; N2S\$
701.

« Last Edit: March 21, 2020, 11:29:56 PM by The Librarian »