Day 024: LCASE$
#11
(12-04-2022, 01:48 PM)SMcNeill Wrote: A better solution, in a case like this, is to minimize the usage of that slow processing string command, as much as possible.
Code: (Select All)
DIM tempArray(UBOUND(Array)) AS STRING
FOR i = 0 TO UBOUND(Array)
    tempArray(i) = LCASE$(Array(i))
NEXT

 FOR x = 0 TO UBOUND(tempArray)
    FOR y = 0 TO UBOUND(tempArray)
        IF tempArray(x) < tempArray(y) THEN SWAP tempArray(x), tempArray(y)
    NEXT
NEXT

FOR i = 0 TO UBOUND(Array)
    Array(i) = tempArray(i)
NEXT

Surely this is a good opportunity to use _StriCmp to keep the code neat while still achieving good performance?

Code: (Select All)
For x = 0 To UBound(Array)
    For y = 0 To UBound(Array)
        If _StriCmp(Array(x), Array(y)) = -1 Then Swap Array(x), Array(y)
    Next
Next
Reply
#12
(12-05-2022, 07:30 AM)luke Wrote: Surely this is a good opportunity to use _StriCmp to keep the code neat while still achieving good performance?
I actually went to look that up to see if such a function existed. But why bother with a bubble sort? How many times did Steve call it "yucky" or similar? The original example was only to demonstrate that "LCASE$()" is slow, although not as slow as concatenation.
Reply
#13
In regard to _StrCmp, it's a bit like my String Comparison routine I made for string math usage, but that was for comparing numbers. I would imagine I'd have to tweak it some to get it to work like the c/c++ StrCmp function.

For positive whole numbers the longer string is the larger number.

Compare "9" to "111"

Results: 111 > 9


but for StrCmp...

Results: -8 where "111" < "9" because the ASCII value of "1" is 8 less than "9"

So StrCmp is not useful for evaluating numbers and I'd have to write a new, but certainly much simpler function to compare strings in this manner. It seems as simple as ASC() in a loop...

Code: (Select All)
WHILE -1
    DO
        INPUT "Press 1 to evaluate two numbers or A to evaluate to words: "; ans$
        IF ans$ = "" THEN SYSTEM
        IF ans$ = "" THEN EXIT WHILE
        IF ans$ = "1" OR LCASE$(ans$) = "a" THEN EXIT DO
    LOOP
    PRINT

    SELECT CASE ans$
        CASE "1" ' Evaluate numbers.
            DO
                INPUT "Number 1: "; n: s1$ = LTRIM$(STR$(n))
                INPUT "Number 2: "; n: s2$ = LTRIM$(STR$(n))
                IF s1$ = "" OR s2$ = "" THEN EXIT DO
                gl% = 0: sm_greater_lesser s1$, s2$, gl%
                SELECT CASE gl%
                    CASE -1: PRINT s1$; " < "; s2$
                    CASE 0: PRINT s1$; " = "; s2$
                    CASE 1: PRINT s1$; " > "; s2$
                END SELECT
                PRINT
            LOOP

        CASE ELSE ' Evaluate words.

            DO
                LINE INPUT "String 1: "; s1$
                LINE INPUT "String 2: "; s2$
                IF s1$ = "" AND s2$ = "" THEN EXIT DO
                PRINT
                x = StrCmp(s1$, s2$)
                SELECT CASE SGN(x)
                    CASE -1: PRINT "StrCmp = "; LTRIM$(STR$(x)); " and "; s1$; " < "; s2$
                    CASE 0: PRINT "StrCmp = "; LTRIM$(STR$(x)); " and "; s1$; " = "; s2$
                    CASE 1: PRINT "StrCmp = "; LTRIM$(STR$(x)); " and "; s1$; " > "; s2$
                END SELECT
                PRINT
            LOOP
    END SELECT
WEND
END

FUNCTION StrCmp (s1$, s2$)
    DO
        i = i + 1
        IF s1$ = "" OR s2$ = "" THEN
            IF LEN(s1$) + LEN(s2$) = 0 THEN x = 0: EXIT DO
            IF s1$ = "" THEN x = -ASC(s2$) ELSE x = ASC(s1$)
        ELSE
            x = ASC(MID$(s1$, i, 1)) - ASC(MID$(s2$, 1))
        END IF
    LOOP UNTIL x OR i >= LEN(s1$) AND i >= LEN(s2$)
    StrCmp = x
END FUNCTION



SUB sm_greater_lesser (stringmatha$, stringmathb$, gl%)
    compa$ = stringmatha$: compb$ = stringmathb$ ' So original variables do not get changed.
    DO
        WHILE -1 ' Falx loop.
            IF gl% = 2 THEN EXIT WHILE ' For bypassing sign and decimal adjustments when only positive non-decimal numbers are being evaluated.
            ' Remove trailing zeros after a decimal point.
            IF INSTR(compa$, ".") THEN
                DO UNTIL RIGHT$(compa$, 1) <> "0" AND RIGHT$(compa$, 1) <> "." AND RIGHT$(compa$, 1) <> "-"
                    compa$ = MID$(compa$, 1, LEN(compa$) - 1)
                LOOP
            END IF
            IF INSTR(compb$, ".") THEN
                DO UNTIL RIGHT$(compb$, 1) <> "0" AND RIGHT$(compb$, 1) <> "." AND RIGHT$(compb$, 1) <> "-"
                    compb$ = MID$(compb$, 1, LEN(compb$) - 1)
                LOOP
            END IF

            IF MID$(compa$, 1, 2) = "-0" OR compa$ = "" OR compa$ = "-" THEN compa$ = "0"
            IF MID$(compb$, 1, 2) = "-0" OR compb$ = "" OR compb$ = "-" THEN compb$ = "0"

            ' A - and +
            j% = 0: k% = 0
            IF LEFT$(compa$, 1) = "-" THEN j% = -1
            IF LEFT$(compb$, 1) = "-" THEN k% = -1
            IF k% = 0 AND j% THEN gl% = -1: EXIT DO
            IF j% = 0 AND k% THEN gl% = 1: EXIT DO

            j&& = INSTR(compa$, ".")
            k&& = INSTR(compb$, ".")

            ' A starting decimal and non-decimal.
            IF j&& = 0 AND k&& = 1 THEN
                IF compa$ = "0" THEN gl% = -1 ELSE gl% = 1
                EXIT DO
            END IF
            IF k&& = 0 AND j&& = 1 THEN
                IF compb$ = "0" THEN gl% = 1 ELSE gl% = -1
                EXIT DO
            END IF

            ' remove decimals and align.
            j2&& = 0: k2&& = 0
            IF j&& <> 0 OR k&& <> 0 THEN
                IF j&& THEN compa$ = MID$(compa$, 1, INSTR(compa$, ".") - 1) + MID$(compa$, INSTR(compa$, ".") + 1): j2&& = LEN(compa$) - j&& + 1
                IF k&& THEN compb$ = MID$(compb$, 1, INSTR(compb$, ".") - 1) + MID$(compb$, INSTR(compb$, ".") + 1): k2&& = LEN(compb$) - k&& + 1
                compa$ = compa$ + STRING$(k2&& - j2&&, "0")
                compb$ = compb$ + STRING$(j2&& - k2&&, "0")
            END IF
            EXIT WHILE
        WEND

        ' Remove leading zeros if any.
        DO UNTIL LEFT$(compa$, 1) <> "0"
            compa$ = MID$(compa$, 2)
        LOOP
        IF compa$ = "" THEN compa$ = "0"
        DO UNTIL LEFT$(compb$, 1) <> "0"
            compb$ = MID$(compb$, 2)
        LOOP
        IF compb$ = "" THEN compb$ = "0"

        ' Both positive or both negative whole numbers.

        SELECT CASE LEN(compa$)
            CASE IS < LEN(compb$)
                gl% = -1
            CASE IS = LEN(compb$)
                IF compa$ = compb$ THEN
                    gl% = 0
                ELSEIF compa$ > compb$ THEN gl% = 1
                ELSEIF compa$ < compb$ THEN gl% = -1
                END IF
            CASE IS > LEN(compb$)
                gl% = 1
        END SELECT
        EXIT DO
    LOOP
END SUB

Pete
Reply




Users browsing this thread: 4 Guest(s)