Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 17:50 08 May 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : When not to convert C to BASIC

Author Message
BobDevries

Senior Member

Joined: 08/06/2011
Location: Australia
Posts: 266
Posted: 11:45am 23 May 2013
Copy link to clipboard 
Print this post

Hello all,

well, after a day of bashing my skull against a brick wall, I finally see the light.

I've been trying to re-create the C macros isdigit(), isalnum() et al. without success.

I found out this morning, that these macros actually use a lookup table and use the value of the character as an index into the table, there to grab the attributes needed for the macro that was called.

So now I've gone back to the non-recommended (in C) way like this:


Function isdigit(IN$)
X$=Left$(IN$,1): X=Asc(X$)
If X > &H2f And X < &H3a Then isdigit = 1 Else isdigit = 0
End Function


Why is it not recommended? 'Cos it doesn't work on all character sets! However, since the MM uses just one such, it's really immaterial.

I'm writing a library of such functions for future use.

REM Just some trivial programming information for you all.

Regards,

Bob Devries
Dalby, QLD, Australia
 
BobD

Guru

Joined: 07/12/2011
Location: Australia
Posts: 935
Posted: 12:13pm 23 May 2013
Copy link to clipboard 
Print this post

Bob

How far do you intend to go with checking character attributes? Check a character is UC, LC, NUM, CTRL, Alt, Function etc.? Some characters would have more than one of these attributes.

A table would be 256 bytes and could be defined in the MMBasic firmware for lookup. A character could have up to 8 different attributes based on 8 bits at the index position. Lookup would be the table address (an MMBasic variable) + the character value.

It may be easier to build functions that way? Any thoughts? Anyone?

Bob
 
kiiid

Guru

Joined: 11/05/2013
Location: United Kingdom
Posts: 671
Posted: 01:15pm 23 May 2013
Copy link to clipboard 
Print this post

I see nothing wrong in the conversion. If it works with ASCII, that is in most cases enough in the non-PC world. I would only have simplified it a bit:

function isdigit(left$(in$,1))
isdigit=val(in$)
end function

Edited by kiiid 2013-05-24
http://rittle.org

--------------
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5915
Posted: 01:41pm 23 May 2013
Copy link to clipboard 
Print this post

using val(IN$) would not find zero

I prefer INSTR. It is useful for punctuation, digits, white space etc as well.

Function isdigit(IN$)
X$=Left$(IN$,1)
If instr("0123456789",x$)> 0 Then isdigit = 1 Else isdigit = 0
End Function

Jim
VK7JH
MMedit   MMBasic Help
 
kiiid

Guru

Joined: 11/05/2013
Location: United Kingdom
Posts: 671
Posted: 01:52pm 23 May 2013
Copy link to clipboard 
Print this post

  TassyJim said   using val(IN$) would not find zero

Jim


Would it? I haven't used it for so long that I have forgotten...
INSTR is also a good choice anyway
http://rittle.org

--------------
 
BobDevries

Senior Member

Joined: 08/06/2011
Location: Australia
Posts: 266
Posted: 02:08pm 23 May 2013
Copy link to clipboard 
Print this post

Just by way of testing that, I found an anomoly:

? VAL("A")

returns 0 as expected, but

? VAL("0")

returns 00

Why?

I condensed the code of isdigit to:

function isdigit(IN$)
IF INSTR(1,"0123456789",LEFT$(IN$,1)) > 0 then isdigit = 1 else isdigit = 0
end function


Regards,
Bob Devries
Dalby, QLD, Australia
 
shoebuckle
Senior Member

Joined: 21/01/2012
Location: Australia
Posts: 189
Posted: 03:31pm 29 May 2013
Copy link to clipboard 
Print this post

I like the simplicity of your IsDigit() function but I was curious to see how fast it was compared with a simple range test and whether it was quicker as a Function or a Subroutine.
I tried an alpha test instead of numeric and because some letters are used more frequently than others in your native language, I tested with a straight alphabet and with a sequence-modified alphabet.
Using a text document I happened to have, I first ran it through ALHHANUM to find the frequency of each alphabetic character to set up the modified alphabet sequence (it contains 87,840 characters). The results of running the 6 small programs show that there is a little under 7% difference in speed between the slowest (Pgm 1) and fastest (Pgm 4), not really enough to worry about which technique is used. The times were obtained on a Mono Maximite.
Cheers,
Hugh


Using SUB Using Function
Instr, A-Z Alphabet Seq Pgm 1 66606 Pgm 3 64669
Instr, Mod Alphabet Seq Pgm 2 64089 Pgm 4 62153
IF/THEN Range test Pgm 5 66474 Phm 6 65188


Program 1
Open "taking.txt" For input As 1
Alpha$="abcdefghijklmnopqrstuvwxyz"
Timer=0
Do
a$=LCase$(Input$(1, #1))
alphatest(a$,p)
Print p;
Loop Until Eof(1)
Print
Print Timer
End

Sub Alphatest(b$,ptr)
ptr=Instr(1,alpha$,b$)
End Sub


Program 2
Open "taking.txt" For input As 1
Alpha$="eatinosrcdhlmfgpuwbkvyjqxz"
Timer=0
Do
a$=LCase$(Input$(1, #1))
alphatest(a$,p)
Print p;
Loop Until Eof(1)
Print
Print Timer
End

Sub Alphatest(b$,ptr)
ptr=Instr(1,alpha$,b$)
End Sub


Program 3
Open "taking.txt" For input As 1
Alpha$="abcdefghijklmnopqrstuvwxyz"
Timer=0
Do
a$=LCase$(Input$(1, #1))
Print IsAlpha(a$);
Loop Until Eof(1)
Print
Print Timer
End

Function IsAlpha(b$)
IsAlpha=Instr(1,alpha$,b$)
End Function


Program 4
Open "taking.txt" For input As 1
Alpha$="eatinosrcdhlmfgpuwbkvyjqxz"
Timer=0
Do
a$=LCase$(Input$(1, #1))
Print IsAlpha(a$);
Loop Until Eof(1)
Print
Print Timer
End

Function IsAlpha(b$)
IsAlpha=Instr(1,alpha$,b$)
End Function


Program 5
Open "taking.txt" For input As 1
Timer=0
Do
a$=LCase$(Input$(1, #1))
alphatest(a$,p)
Print p;
Loop Until Eof(1)
Print
Print Timer
End

Sub Alphatest(b$,ptr)
If b$>="a" And b$<="z" Then ptr=1 Else ptr=0
End Sub


Program 6
Open "taking.txt" For input As 1
Timer=0
Do
a$=LCase$(Input$(1, #1))
Print IsAlpha(a$);
Loop Until Eof(1)
Print
Print Timer
End

Function IsAlpha(b$)
If b$>="a" And b$<="z" Then isAlpha=1 Else IsAlpha=0
End Function
Edited by shoebuckle 2013-05-31
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3671
Posted: 08:34pm 29 May 2013
Copy link to clipboard 
Print this post

Does this work?

Function IsAlpha(b$)
IsAlpha = (b$>="a" And b$<="z")
End Function

Maybe the parens aren't needed.

Has to be faster.

BTW, I think PRINT will be the major slow thing and hides the difference in speed.

John
 
shoebuckle
Senior Member

Joined: 21/01/2012
Location: Australia
Posts: 189
Posted: 10:25pm 29 May 2013
Copy link to clipboard 
Print this post

Yes John, it works and is faster. Replacing the line in Pgm 6's Function gives a time of 57468.

Now if we:
- Remove Print P; in programs 1,2 and 5 and
- Replace Print IsAlpha(a$); with a=Isalpha(A$) in pgms 3,4, and 7
and run again we get:
Pgm 1 30341
Pgm 2 30261
Pgm 3 29828
Pgm 4 29748
Pgm 5 35830
Pgm 6 35901
Pgm 7 28901 Using your IsAlpha=(b$>="a" and b$<="z") in Pgm 6

The objective was to test the speed of the code in the Sub or Function and see if it made much difference so, where possible I used the same overhead (calling code). You might complain that in removing the PRINT, I replaced the calling code in 3, 4 and 7 with an assignment statement a=IsAlpha(a$) however I believe this is valid as the SUB returns the value of the test in p which means both methods return a value to a variable. The argument against this is that you might use the Function back in the mainline to say, for instance:

If IsAlpha(a$) then ...

and this would be faster than using a SUB.

Anyway you can see that there is little difference between using the straight alphabet and the modified alpha sequence (comparing the pairs 1 & 2 and 3 & 4). Likewise not much difference between 5 & 6 (Sub vs Function).

All rather academic really, unless you are trying to squeeze the last ounce of performance out of the system.
Cheers,
Hugh
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 10:27pm 29 May 2013
Copy link to clipboard 
Print this post

how about this one:
The conversion to lowercase should be in the IsAlpa function to prevent wrong use.
[code]
Open "taking.txt" For input As 1
Timer=0
Do
a=IsAlpha(Input$(1, #1))
Loop Until Eof(1)
Print
Print Timer
End

Function IsAlpha(b$)
c = asc(b$)
isAlpha=((c>64 and c<91) or ( c > 96 and c < 123))
End Function
[/code]
I am not sure if MMBasic shortcircuits, if not then this can be an alternative.
[code]
Function IsAlpha(b$)
c = asc(b$)
if c < 91) then
IsAlpha = (c > 64)
else
if c < 123 then
IsAlpha = (c > 96)
end if
end if
End Function
[/code]
Edited by TZAdvantage 2013-05-31
Microblocks. Build with logic.
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3671
Posted: 10:36pm 29 May 2013
Copy link to clipboard 
Print this post

As it's not very sensitive to changes it suggests MMBasic is just very busy going round and round (tokenising and executing etc).

Although how to speed it up is reasonably well known (compile / semi-compile, run from RAM, faster CPU, etc), does it matter?

I mean - are people finding it is too slow?

(Benchmarks are fun, of course.)

John
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 10:38pm 29 May 2013
Copy link to clipboard 
Print this post

If it can be made faster it is by definition too slow. :)

It is a bit of a lost art unfortunately. Java is to blame for that. :)



Edited by TZAdvantage 2013-05-31
Microblocks. Build with logic.
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3165
Posted: 12:00am 30 May 2013
Copy link to clipboard 
Print this post

  BobDevries said   Just by way of testing that, I found an anomoly:

? VAL("A")

returns 0 as expected, but

? VAL("0")

returns 00

Why?

I just tested that and it works fine (ie, returns 0 in both cases).

Geoff
Geoff Graham - http://geoffg.net
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3671
Posted: 12:51am 30 May 2013
Copy link to clipboard 
Print this post

  TZAdvantage said   If it can be made faster it is by definition too slow. :)

LOL

Except some actually may think it's true. Unless it's unacceptably slow, aim for maintainability, robustness etc.

John
 
shoebuckle
Senior Member

Joined: 21/01/2012
Location: Australia
Posts: 189
Posted: 03:03pm 31 May 2013
Copy link to clipboard 
Print this post

  TZAdvantage said   how about this one:
The conversion to lowercase should be in the IsAlpa function to prevent wrong use.
[code]
Open "taking.txt" For input As 1
Timer=0
Do
a=IsAlpha(Input$(1, #1))
Loop Until Eof(1)
Print
Print Timer
End

Function IsAlpha(b$)
c = asc(b$)
isAlpha=((c>64 and c<91) or ( c > 96 and c < 123))
End Function
[/code]
I am not sure if MMBasic shortcircuits, if not then this can be an alternative.
[code]
Function IsAlpha(b$)
c = asc(b$)
if c < 91) then
IsAlpha = (c > 64)
else
if c < 123 then
IsAlpha = (c > 96)
end if
end if
End Function
[/code]


The first one takes 33920
The second 35002 (after making Endif all one word in both instances).

You pays your money, you takes your choice! They all work.
Hugh
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 11:27pm 31 May 2013
Copy link to clipboard 
Print this post

Thanks for the test.
It shows that string comparison is faster then numeric comparisons.
An unexpected result.
Probably have to do that numbers are floats instead of integers.

Microblocks. Build with logic.
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024