How do I test for integers
-
- Posts: 21
- Joined: Sun 15 May 2022, 11:35
How do I test for integers
I could not find any information about this in the documents. How do I test a variable for its type?
Re: How do I test for integers
To test the value of a numeric variable to see if it's an integer you can simply do:
Code: Select all
IF var = INT(var) THEN...
If that's really what you need, I think this code works:
Code: Select all
IF !(^var + 8) AND &FFFF THEN PRINT "Floating-point" ELSE PRINT "Integer"
Code: Select all
var = 123
IF !(^var + 8) AND &FFFF THEN PRINT "Floating-point" ELSE PRINT "Integer"
var = 123.0
IF !(^var + 8) AND &FFFF THEN PRINT "Floating-point" ELSE PRINT "Integer"
-
- Posts: 41
- Joined: Sat 28 May 2022, 22:40
Re: How do I test for integers
So to clarify this for the layperson,
BBC Basic has a specific type for integer variables, with the % flag, 32-bit signed.
Is it the case that a normal numeric variable is stored in integer format until it is assigned a non-integer value?
So the code presented above inspects the variable's storage location to determine whether the format is floating-point or integer?
I realise there is a possibly significant processing (speed) as well as a numerical accuracy advantage in keeping numbers to integer whilst they can, has that been in BBC Basic since Acorn 1982 or introduced later?
As I recall, Sinclair Basic, which does not have a specific integer type, also does this for the same reasons.
There's another advantage in that the numeric variable type has a greater range than the integer type.
Would LET var=INT(var+.5) force it back to being stored as an integer?
OK I've played with a code snippet
Entering 1 responds Integer
Entering 1.0 responds Floating-point
Entering num responds Floating-point
Entering INT(num+.5) responds Integer
BBC Basic has a specific type for integer variables, with the % flag, 32-bit signed.
Is it the case that a normal numeric variable is stored in integer format until it is assigned a non-integer value?
So the code presented above inspects the variable's storage location to determine whether the format is floating-point or integer?
I realise there is a possibly significant processing (speed) as well as a numerical accuracy advantage in keeping numbers to integer whilst they can, has that been in BBC Basic since Acorn 1982 or introduced later?
As I recall, Sinclair Basic, which does not have a specific integer type, also does this for the same reasons.
There's another advantage in that the numeric variable type has a greater range than the integer type.
Would LET var=INT(var+.5) force it back to being stored as an integer?
OK I've played with a code snippet
Code: Select all
MODE 7
REPEAT
INPUT TAB(0,23)"Submit number to test ";num$
num=EVAL(num$)
PRINT TAB(0,0)num;" is type ";FNisint(num);SPC(7)
UNTIL num=0
END
DEF FNisint(var)
IF !(^var + 8) AND &FFFF THEN ="Floating-point" ELSE ="Integer"
Entering 1.0 responds Floating-point
Entering num responds Floating-point
Entering INT(num+.5) responds Integer
Started using BASIC circa 1981 with CP/M, Video Genie, Sinclair ZX81, Acorn Atom, and progressed with ZX Spectrum, BBC Micro and Sinclair QL, Cambridge Z88, DOS, Windows. Wrote A-level project using school's BBC Micro with dual 800K floppy drive.
-
- Posts: 21
- Joined: Sun 15 May 2022, 11:35
Re: How do I test for integers
[quote="Hated Moron" post_id=4087 time=1654290713 user_id=414]
Thanks. It seems that this is what I wanted but I couldn't make it work.
(By the way, I just learned that in BASIC True==> -1 and False==>0)
So, I have this little code to convert minutes and seconds to seconds.
I want to test that the user enters an integer and not a string or a decimal number.
But, when I run the above program
I enter a string "abc" but the test returns -1.
I guess I'm looking something like in Python.
Thanks again for your help.
Code: Select all
IF var = INT(var) THEN...
(By the way, I just learned that in BASIC True==> -1 and False==>0)
So, I have this little code to convert minutes and seconds to seconds.
Code: Select all
REM Convert minutes and seconds to seconds
INPUT "Enter minutes:";Minutes%
PRINT Minutes%=INT(Minutes%)
IF Minutes=INT(Minutes) THEN
INPUT "Enter seconds:";Seconds%
PRINT Minutes%*60+Seconds%;" " "Seconds"
ELSE
PRINT "Enter an integer"
ENDIF
END
But, when I run the above program
Code: Select all
Enter minutes:? abc
-1
Enter seconds:?
I guess I'm looking something like
Code: Select all
type()
Thanks again for your help.
Re: How do I test for integers
The code you listed was:
Code: Select all
INPUT "Enter minutes:";Minutes%
If you are concerned about whether it's an integer or a non-integer you must ensure that what he enters is placed in a regular (variant) numeric variable (e.g. Minutes); then you can perform the test. But that still won't tell you whether he entered something that isn't even numeric.
To perform that additional test you would have to place what he enters into a string variable and then do all the testing yourself in BASIC code. In its most simplistic form that could be something like:
Code: Select all
INPUT "Enter minutes:";Minutes$
IF STR$(VAL(Minutes$)) <> Minutes$ THEN PRINT "Not a number"
IF INT(VAL(Minutes$)) <> VAL(Minutes$) THEN PRINT "Not an integer"
Re: How do I test for integers
I don't know Python, but I should perhaps have added to my previous reply that BBC BASIC doesn't have a variable type which can contain either a numeric or a string (what I might call a 'true variant'). In principle it easily could, because internally it does indeed have such a data type - it's necessary to hold the value returned from a user-defined function (DEF FN) because that can be an integer, a floating-point number or a string:zeynel1 wrote: ↑Sat 04 Jun 2022, 06:20 I guess I'm looking something likein Python.Code: Select all
type()
Code: Select all
DEF FNvariant
CASE RND(3) OF
WHEN 1: = 1234
WHEN 2: = 56.78
WHEN 3: = "string"
ENDCASE
= 0 : REM should never happen
-
- Posts: 41
- Joined: Sat 28 May 2022, 22:40
Re: How do I test for integers
The way I'd approach that, is to restrict the user to only entering the allowed characters.zeynel1 wrote: ↑Sat 04 Jun 2022, 06:20So, I have this little code to convert minutes and seconds to seconds.
I want to test that the user enters an integer and not a string or a decimal number.Code: Select all
REM Convert minutes and seconds to seconds INPUT "Enter minutes:";Minutes% PRINT Minutes%=INT(Minutes%) IF Minutes=INT(Minutes) THEN INPUT "Enter seconds:";Seconds% PRINT Minutes%*60+Seconds%;" " "Seconds" ELSE PRINT "Enter an integer" ENDIF END
Allow only digits, no alphabetic characters or punctuation, and the input will definitely be integer.
Something quickly like:
Code: Select all
Minutes%=VAL(FNinput("Enter minutes:","0123456789"))
DEFFNinput(prompt$,allowed$)
input$=""
PRINT prompt$;
REPEAT
key$=GET$
IF INSTR(allowed$,key$) input$=input$+key$: PRINT key$;
UNTIL ASC(key$)=13
=input$
I wouldn't be surprised to discover several suitable routines already written.
You could go further in this instance and only accept valid values between '00' and '59', ie. reject digits 6 and greater for the first digit and limit to two digits.
Hated Moron wrote: ↑Sat 04 Jun 2022, 08:35internally it does indeed have such a data type - it's necessary to hold the value returned from a user-defined function (DEF FN) because that can be an integer, a floating-point number or a string:-
So whilst BBC BASIC does internally use a 'true variant', that is not exposed to the programmer as a variable type.
Code: Select all
Minutes%=FNinput("Enter minutes:","0123456789")
response$=FNinput("Yes/No:","NYny")
DEFFNinput(prompt$,allowed$)
input$=""
PRINT prompt$;
REPEAT
key$=GET$
IF INSTR(allowed$,key$) input$=input$+key$: PRINT key$;
UNTIL ASC(key$)=13
IF input$=STR$(VAL(input$)) = VAL(input$) ELSE =input$
Started using BASIC circa 1981 with CP/M, Video Genie, Sinclair ZX81, Acorn Atom, and progressed with ZX Spectrum, BBC Micro and Sinclair QL, Cambridge Z88, DOS, Windows. Wrote A-level project using school's BBC Micro with dual 800K floppy drive.
Re: How do I test for integers
Here you have a function FNinput() which can return either a string or a number. On the first call of that function you assign the returned value to a numeric variable (Minutes%) so if the function happened to return a string an error would result. Similarly on the second call of the function you assign its value to a string variable, so if a number were to be returned an error would also result!nvingo wrote: ↑Sat 04 Jun 2022, 11:32Code: Select all
Minutes%=FNinput("Enter minutes:","0123456789") response$=FNinput("Yes/No:","NYny") DEFFNinput(prompt$,allowed$) input$="" PRINT prompt$; REPEAT key$=GET$ IF INSTR(allowed$,key$) input$=input$+key$: PRINT key$; UNTIL ASC(key$)=13 IF input$=STR$(VAL(input$)) = VAL(input$) ELSE =input$
Exactly this happens in practice: if I respond to the first prompt by pressing just the Enter key (carriage return), i.e. not typing a number at all, an (empty) string is returned and a Type mismatch error results. That surely cannot be the intended behaviour?
A similar issue could arise if you added a decimal point (in order to allow entry of non-integer values) and/or a minus sign (to allow negative values) to the list of acceptable characters; then, too, the code could easily fail with an untrapped error.
I would most definitely not recommend that approach!
-
- Posts: 41
- Joined: Sat 28 May 2022, 22:40
Re: How do I test for integers
You do realise that the whole point is to PREVENT a string from being typed in when a number is requested - it was only a quick modification of the previous code just to demonstrate that a function could return different types as per your own assertion I quoted - and yes I hadn't anticipated the case where a string was requested and digits were specified as valid characters which could lead to an evaluation of the string as numeric, but in the example posted, digits could not be entered for a yes/no response and it would not attempt to return a numeric value.Hated Moron wrote: ↑Sat 04 Jun 2022, 13:11Here you have a function FNinput() which can return either a string or a number. On the first call of that function you assign the returned value to a numeric variable (Minutes%) so if the function happened to return a string an error would result. Similarly on the second call of the function you assign its value to a string variable, so if a number were to be returned an error would also result!
It's easy enough to trap the specific cases where the input string is either null, '-' or '.'Hated Moron wrote: ↑Sat 04 Jun 2022, 13:11if I respond to the first prompt by pressing just the Enter key (carriage return), i.e. not typing a number at all, an (empty) string is returned and a Type mismatch error results. That surely cannot be the intended behaviour?
A similar issue could arise if you added a decimal point (in order to allow entry of non-integer values) and/or a minus sign (to allow negative values) to the list of acceptable characters; then, too, the code could easily fail with an untrapped error.
I did state that the function offered needed some more work (delete/edit) and assuming the OP is writing a program to perform calculations on time measurements, would at least be capable of adding any necessary or ask here for further responses.
A more tailored way would be to present the input as list or scroll boxes like in the actual clock adjust dialogue:
23⇳ 59⇳ 59⇳ 99⇳ (mock-up).
edited
Started using BASIC circa 1981 with CP/M, Video Genie, Sinclair ZX81, Acorn Atom, and progressed with ZX Spectrum, BBC Micro and Sinclair QL, Cambridge Z88, DOS, Windows. Wrote A-level project using school's BBC Micro with dual 800K floppy drive.
Re: How do I test for integers
Yes, but my point was that the design of the function made it inherently 'fragile', that is prone to failing unless all edge cases (at least one of which you admit you missed) are caught. For that reason it's the sort of code which, in my opinion, should be avoided in favour of an approach which is more fail-safe.
More specifically, I would suggest that a function which can return either a string or a numeric is never a sensible approach, unless the result is used in a context when both types can be accepted, which practically means only in a PRINT list.