# Need Help XB and nested If's

## Recommended Posts

I've never been able to figure out how to do nested if's, in XB. I am trying to implement checking for a leap year.

I can do that thing in c or pascal, but can't figure out how to do that in XB - even brute forcing it.

Microsoft says the correct STEPS are:

How to determine whether a year is a leap year

To determine whether a year is a leap year, follow these steps:

1. If the year is evenly divisible by 4, go to step 2. Otherwise, go to step 5.
2. If the year is evenly divisible by 100, go to step 3. Otherwise, go to step 4.
3. If the year is evenly divisible by 400, go to step 4. Otherwise, go to step 5.
4. The year is a leap year (it has 366 days).
5. The year is not a leap year (it has 365 days).

Some example java code - which would look about the same in c or pascal ...

So basically a top end IF with more IF's in a block.

Can anyone help with how to do something like that in XB?

``````public class Main {

public static void main(String[] args) {

// year to be checked
int year = 1996;
boolean leap = false;

// if the year is divided by 4
if (year % 4 == 0) {

// if the year is century
if (year % 100 == 0) {

// if year is divided by 400
// then it is a leap year
if (year % 400 == 0)
leap = true;
else
leap = false;
}

// if the year is not century
else
leap = true;
}

else
leap = false;

if (leap)
System.out.println(year + " is a leap year.");
else
System.out.println(year + " is not a leap year.");
}
}``````

##### Share on other sites

Just add line numbers to each line:

```  'Leap Year Determination Program (LEAP.BAS)
INPUT "Year (eg 1998)";yr
leap\$="N"
IF yr MOD 4 = 0 THEN leap\$ = "Y"
IF yr MOD 100 = 0 THEN leap\$ ="N"
IF yr MOD 400 = 0 THEN leap\$ = "Y"
IF leap\$ = "Y" THEN
PRINT yr; " is a leap year"
ELSE
PRINT yr; " is NOT a leap year"
END IF```

##### Share on other sites

The bigger problem here is the lack of the MOD operator in XB.

##### Share on other sites

I think this will work:

Using Rich's example.   Use:

IF yr / 4 = INT(yr / 4 ) THEN leap\$ = "Y"

etc.

##### Share on other sites

Well mod is easy to duplicate in XB:

PRINT 5/2=INT(D)

PRINT D*2=INT(M)

PRINT 5-D=INT(MOD)

PRINT INT(MOD)

MOD = INT(1)

ANOTHER EXAMPLE:

PRINT 23/7=INT(D)

PRINT D*7=INT(M)

PRINT 23-M=INT(MOD)

PRINT INT(MOD)

MOD = INT(2)

Not really that complicated using XB.

##### Share on other sites

to add to Rich's post, DEF can get you close to MOD though you only get one parameter.

100 DEF MOD(XX)=YR-INT(YR/XX)*XX
200 FOR YR=2096 TO 2104
400 LEAP\$="NOT LEAP"!RESET
410 IF MOD(4)<>0 THEN 500
420 IF MOD(100)<>0 THEN 450
430 IF MOD(400)<>0 THEN 500
450 LEAP\$="LEAP"
500 PRINT YR;LEAP\$
550 NEXT YR

##### Share on other sites
5 hours ago, dhe said:

Microsoft says the correct STEPS are:

You're taking your example from Microsoft???

There have been many occurrences of leap year bugs:

• Microsoft Excel has, since its earliest versions, incorrectly considered 1900 to be a leap year, and therefore that February 29 comes between February 28 and March 1 of that year. The bug originated from Lotus 1-2-3, and was purposely implemented in Excel for the purpose of backward compatibility. Microsoft has written an article about this bug, explaining the reasons for treating 1900 as a leap year.[7] This bug has been promoted into a requirement in the Ecma Office Open XML (OOXML) specification.[8][9]

• 1
• 1

##### Share on other sites
1 hour ago, dgrissom said:

I think this will work:

Using Rich's example.   Use:

IF yr / 4 = INT(yr / 4 ) THEN leap\$ = "Y"

etc.

### Bad leap year algorithm (many languages)

The following code is an example of a leap year bug that is seen in many languages. It may cause either a Category 1 or Category 2 impact, depending on what the result is used for. It incorrectly assumes that a leap year occurs exactly every four years.[6]

```bool isLeapYear = year % 4 == 0;
```

The correct leap year algorithm is explained at Leap Year Algorithm.

Uhoh, this looks familiar!

##### Share on other sites
Posted (edited)

Here it is with the important code all in one line:

```
10 INPUT Y
20 LY=-((Y/4)=INT(Y/4))+((Y/100)=INT(Y/100))-((Y/400)=INT(Y/400))
30 PRINT "LEAPYEAR=";LY
40 GOTO 10```

If LY=1 then it is a leap year, if 0 then it is not a leap year. To explain:

-((Y/4)=INT(Y/4)) returns a value of 1 if true and 0 if false, so if the year is divisible by 4 then LY=1.

Then ((Y/100)=INT(Y/100))  returns a value of -1 if true and 0 if false, so if the year is divisible by 100 then 1 is subtracted from LY, making it 0.

Then -((Y/400)=INT(Y/100)) returns a value of 1 if the year is divisible by 400

(Edit) This is a tiny bit more compact:

20 LY=((Y AND 3)>0)-((Y/100)<>INT(Y/100))-((Y/400)=INT(Y/400))

Edited by senior_falcon
• 3
• 1

##### Share on other sites
```PTM    TEXT '1155P2122299352*'

MOVB @PTM+12,R3
SWPB R3
INC  R3
CI   R3,>34
JNE  NEXT6
LI   R3,>3100
MOVB R3,@PTM+12
NEXT6  SWPB R3
MOVB R3,@PTM+12```

This is what I've been using since '99... Part of the first assembly program I'd ever coded to date that used compares and conditional jumps. I wrote it based on the assumption that nothing more than incrementing and limits were required to produce an accurate clock/calendar.

I seem to recall running it through a minute-by-minute high-speed advance of 10 years, without once setting off the S-D mechanism. I'm still here, so it must-be accurate?

• 1
• 1

##### Share on other sites

Thank you all for your help.

Senior_Falcon thanks most of all, you laid out the example in code and words, I think if I take each part one at a time, I can figure out, how to snap them together to make multiple if...

Guess I've just been 'spoiled' by if {block if {block}} !

• 2
• 1

##### Share on other sites

So, it seems that I owe this thread a debt of gratitude ...for helping me notice the not-so-much a bug, as more of a logic error.

I was under the impression that leap year came every 3 years!

```ADV9   CLR  R3
MOVB @PTM+12,R3
SWPB R3
INC  R3
CI   R3,>34
JNE  NEXT6
LI   R3,>0030
NEXT6  SWPB R3
MOVB R3,@PTM+12```

So, before... the program worked correctly, but was wrong!
Whereas now... the program works wrongly, but is correct.

All done.

• 2
• 2

##### Share on other sites
8 hours ago, dhe said:

I think if I take each part one at a time, I can figure out, how to snap them together to make multiple if...

see post #6 if you are aiming for IF/THEN statements.

##### Share on other sites
On 8/5/2021 at 3:42 AM, senior_falcon said:

20 LY=((Y AND 3)>0)-((Y/100)<>INT(Y/100))-((Y/400)=INT(Y/400))

very elegant!

I fell in love with those boolean expressions when a friend of my father showed it to me back in 1983 .. often much faster than IF-THEN. But I didn't know the "AND" trick for MOD. I guess I have to update my TiCodEd Standard-Library, currently

```sub mod(n,d,m)
m = n - int(n/d) * d
subend```

The AND calculation takes only one third of the time.

Talking of IF-THEN, we did not really answer the original question this way...

##### Share on other sites

Guess I need to add MOD(number,divisor,remainder) to RXB in Assembly ROMs.

NUMBER=5

DIVISOR=2

REMAINDER=1

or

NUMBER=23

DIVISOR=7

REMAINDER=2

##### Share on other sites
27 minutes ago, RXB said:

Guess I need to add MOD(number,divisor,remainder) to RXB in Assembly ROMs.

NUMBER=5

DIVISOR=2

REMAINDER=1

or

NUMBER=23

DIVISOR=7

REMAINDER=2

Out of curiosity, is it not possible to make MOD an operator like AND and OR?  Doing so you could have a proper statement of 2021 MOD 4, &c.

##### Share on other sites
52 minutes ago, OLD CS1 said:

Out of curiosity, is it not possible to make MOD an operator like AND and OR?  Doing so you could have a proper statement of 2021 MOD 4, &c.

NO unlike others 2 parameters are needed and returns one the remainder.

I guess MIN(low,high) or MAX(high,low) could be used instead.

So you would need to assign a variable:

X=MOD(number,divisor)

X would be the result like X would equal 2 for X=MOD(23,7)

##### Share on other sites
4 hours ago, RXB said:

NO unlike others 2 parameters are needed and returns one the remainder.

I guess MIN(low,high) or MAX(high,low) could be used instead.

So you would need to assign a variable:

X=MOD(number,divisor)

X would be the result like X would equal 2 for X=MOD(23,7)

Rich if you are going to add MOD you might want a DIV function too, that returns two values, the dividend and the remainder.

Forth uses this and it is baked in to the 9900 DIV instruction anyway.

Just a thought.

##### Share on other sites
7 hours ago, TheBF said:

... you might want a DIV function too, that returns two values, the dividend and the remainder.

That would be the quotient and the remainder. 🙂

...lee

##### Share on other sites
1 hour ago, Lee Stewart said:

That would be the quotient and the remainder. 🙂

...lee

Yes it would.

Thank you.

##### Share on other sites
14 hours ago, RXB said:

So you would need to assign a variable:

X=MOD(number,divisor)

X would be the result like X would equal 2 for X=MOD(23,7)

Rich, would you need a new token for this?

##### Share on other sites
3 hours ago, Lee Stewart said:

That would be the quotient and the remainder. 🙂

For quite a while I believed that "rational numbers" got their name because they were in some sense "good", "understandable", while the "irrational numbers" were the opposite.

But rational numbers are merely those that can be expressed by a ratio (a/b). Often, the simpler explanation is the better one.

##### Share on other sites
2 hours ago, SteveB said:

Rich, would you need a new token for this?

We have a ton of free tokens in XB:

Spoiler

***********************************************************
*                BASIC KEYWORD TABLE
*      THE TOKEN IS ITS LEFT BINDING POWER
***********************************************************
KEYTAB DATA CHAR1,CHAR2,CHAR3,CHAR4,CHAR5
DATA CHAR6,CHAR7,CHAR8,CHAR9,CHARA
CHAR1  TEXT '!'
BYTE TREMZ             *  !
TEXT '#'
BYTE NUMBEZ            *  #
TEXT '&'
BYTE CONCZ             *  &
TEXT '('
BYTE LPARZ             *  (
TEXT ')'
BYTE RPARZ             *  )
TEXT '*'
BYTE MULTZ             *  *
TEXT '+'
BYTE PLUSZ             *  +
TEXT ','
BYTE COMMAZ            *  ,
TEXT '-'
BYTE MINUSZ            *  -
TEXT '/'
BYTE DIVIZ             *  /
TEXT ':'
BYTE COLONZ            *  :
TEXT ';'
BYTE SEMICZ            *  ;
TEXT '<'
BYTE LESSZ             *  <
TEXT '='
BYTE EQUALZ            *  =
TEXT '>'
BYTE GREATZ            *  >
TEXT '^'
BYTE CIRCUZ            *  ^
BYTE >FF
CHAR2  TEXT '::'
BYTE SSEPZ             *  ::
TEXT 'AT'
BYTE ATZ               *  AT
TEXT 'GO'
BYTE GOZ               *  GO * RXB MOTION
TEXT 'IF'
BYTE IFZ               *  IF
TEXT 'ON'
BYTE ONZ               *  ON * RXB ONKEY
TEXT 'OR'
BYTE ORZ               *  OR
TEXT 'PI'
BYTE PIZ               *  PI
TEXT 'TO'
BYTE TOZ               *  TO
BYTE >FF
CHAR3  TEXT 'ABS'
BYTE ABSZ              *  ABS
TEXT 'ALL'
BYTE ALLZ              *  ALL
TEXT 'AND'
BYTE ANDZ              *  AND
TEXT 'ASC'
BYTE ASCZ              *  ASC
TEXT 'ATN'
BYTE ATNZ              *  ATN
TEXT 'BYE'
BYTE >03               *  BYE
TEXT 'CON'
BYTE >01               *  CONtinue
TEXT 'COS'
BYTE COSZ              *  COS
TEXT 'DEF'
BYTE DEFZ              *  DEF
TEXT 'DEL'
BYTE >09               *  DEL
TEXT 'DIM'
BYTE DIMZ              *  DIM
TEXT 'END'
BYTE ENDZ              *  END
TEXT 'EOF'
BYTE EOFZ              *  EOF
TEXT 'EXP'
BYTE EXPZZ             *  EXP
TEXT 'FOR'
BYTE FORZ              *  FOR
TEXT 'INT'
BYTE INTZ              *  INT
TEXT 'LEN'
BYTE LENZ              *  LEN
TEXT 'LOG'
BYTE LOGZ              *  LOG
TEXT 'MAX'
BYTE MAXZ              *  MAX
TEXT 'MIN'
BYTE MINZ              *  MIN
TEXT 'NEW'
BYTE >00               *  NEW * RXB CALL NEW
TEXT 'NOT'
BYTE NOTZ              *  NOT
TEXT 'NUM'
BYTE >04               *  NUMber
TEXT 'OLD'
BYTE >05               *  OLD * RXB SAMS
TEXT 'POS'
BYTE POSZ              *  POS
TEXT 'REC'
BYTE RECZ              *  REC
TEXT 'REM'
BYTE REMZ              *  REMark
TEXT 'RES'
BYTE >06               *  RESequence
TEXT 'RND'
BYTE RNDZ              *  RND * RXB CHANGED
TEXT 'RUN'
BYTE RUNZ              *  RUN * RXB SAMS
TEXT 'SGN'
BYTE SGNZZ             *  SGN
TEXT 'SIN'
BYTE SINZ              *  SIN
TEXT 'SQR'
BYTE SQRZ              *  SQR
TEXT 'SUB'
BYTE SUBZ              *  SUB
TEXT 'TAB'
BYTE TABZ              *  TAB
TEXT 'TAN'
BYTE TANZ              *  TAN
TEXT 'VAL'
BYTE VALZ              *  VAL
TEXT 'XOR'
BYTE XORZ              *  XOR
BYTE >FF
CHAR4  TEXT 'BASE'
BYTE BASEZ             *  BASE
TEXT 'BEEP'
BYTE BEEPZ             *  BEEP
TEXT 'CALL'
BYTE CALLZ             *  CALL
TEXT 'CHR\$'
BYTE CHRZZ             *  CHR\$
TEXT 'COPY'
BYTE >0A               *  COPY
TEXT 'DATA'
BYTE DATAZ             *  DATA
TEXT 'ELSE'
BYTE ELSEZ             *  ELSE
TEXT 'GOTO'
BYTE GOTOZ             *  GOTO * RXB ONKEY
TEXT 'LIST'
BYTE >02               *  LIST
TEXT 'MOVE'
BYTE >0B               *  MOVE
TEXT 'NEXT'
BYTE NEXTZ             *  NEXT
TEXT 'OPEN'
BYTE OPENZ             *  OPEN
TEXT 'RPT\$'
BYTE RPTZZ             *  RPT\$
TEXT 'SAVE'
BYTE >07               *  SAVE * RXB SAVE IV254
TEXT 'SEG\$'
BYTE SEGZZ             *  SEG\$
TEXT 'SIZE'
BYTE SIZEZ             *  SIZE * RXB CALL SIZE
TEXT 'STEP'
BYTE STEPZ             *  STEP
TEXT 'STOP'
BYTE STOPZ             *  STOP * RXB MOTION
TEXT 'STR\$'
BYTE STRZZ             *  STR\$
TEXT 'THEN'
BYTE THENZ             *  THEN
BYTE >FF
CHAR5  TEXT 'BREAK'
BYTE BREAKZ            *  BREAK
TEXT 'CLOSE'
BYTE CLOSEZ            *  CLOSE
TEXT 'DIGIT'
BYTE DIGITZ            *  DIGIT
TEXT 'ERASE'
BYTE ERASEZ            *  ERASE
TEXT 'ERROR'
BYTE ERRORZ            *  ERROR
TEXT 'FIXED'
BYTE FIXEDZ            *  FIXED
TEXT 'GOSUB'
BYTE GOSUBZ            *  GOSUB
TEXT 'IMAGE'
BYTE IMAGEZ            *  IMAGE
TEXT 'INPUT'
BYTE INPUTZ            *  INPUT
TEXT 'MERGE'
BYTE >08               *  MERGE
TEXT 'PRINT'
BYTE PRINTZ            *  PRINT
TEXT 'TRACE'
BYTE TRACEZ            *  TRACE
TEXT 'USING'
BYTE USINGZ            *  USING
BYTE >FF
CHAR6  TEXT 'ACCEPT'
BYTE ACCEPZ            *  ACCEPT
TEXT 'APPEND'
BYTE APPENZ            *  APPEND
TEXT 'DELETE'
BYTE DELETZ            *  DELETE
TEXT 'LINPUT'
BYTE LINPUZ            *  LINPUT
TEXT 'NUMBER'
BYTE >04               *  NUMBER
TEXT 'OPTION'
BYTE OPTIOZ            *  OPTION
TEXT 'OUTPUT'
BYTE OUTPUZ            *  OUTPUT
TEXT 'RETURN'
BYTE RETURZ            *  RETURN
TEXT 'SUBEND'
BYTE SUBNDZ            *  SUBEND
TEXT 'UALPHA'
BYTE UALPHZ            *  UALPHA
TEXT 'UPDATE'
BYTE UPDATZ            *  UPDATE
BYTE >FF
CHAR7  TEXT 'DISPLAY'
BYTE DISPLZ            *  DISPLAY
TEXT 'NUMERIC'
BYTE NUMERZ            *  NUMERIC
TEXT 'RESTORE'
BYTE RESTOZ            *  RESTORE
TEXT 'SUBEXIT'
BYTE SUBXTZ            *  SUBEXIT
TEXT 'UNBREAK'
BYTE UNBREZ            *  UNBREAK
TEXT 'UNTRACE'
BYTE UNTRAZ            *  UNTRACE
TEXT 'WARNING'
BYTE WARNZ             *  WARNING
BYTE >FF
CHAR8  TEXT 'CONTINUE'
BYTE >01               *  CONTINUE
TEXT 'INTERNAL'
BYTE INTERZ            *  INTERNAL
TEXT 'RELATIVE'
BYTE RELATZ            *  RELATIVE
TEXT 'VALIDATE'
BYTE VALIDZ            *  VALIDATE
TEXT 'VARIABLE'
BYTE VARIAZ            *  VARIABLE
BYTE >FF
CHAR9  TEXT 'RANDOMIZE'
BYTE RANDOZ            *  RANDOMIZE
BYTE >FF
CHARA  TEXT 'SEQUENTIAL'
BYTE SEQUEZ            *  SEQUENTIAL
BYTE >FF
***********************************************************

Currently token symbols not assigned:

>80, >AB, >AC, >AD, >AE, >AF, >B9, >C6, >E2, >E3, >E4, >E5, >E6, >E7, >F2

So I would pick >AB for MOD and >AC for DIV

##### Share on other sites
4 minutes ago, RXB said:

So I would pick >AB for MOD and >AC for DIV

As I try to keep TiCodEd RXB-compatible I would need to add them as well in my tokenizer.

##### Share on other sites
22 minutes ago, SteveB said:

As I try to keep TiCodEd RXB-compatible I would need to add them as well in my tokenizer.

No rush RXB 2021 is a long way off.

## Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.