Page **15** of **27**

### Re: Introduction to BBC BASIC

Posted: **Tue Jul 16, 2019 7:58 pm**

by **Soruk**

RichardRussell wrote: ↑Tue Jul 16, 2019 5:57 pm

Soruk wrote: ↑Tue Jul 16, 2019 4:58 pm

This has, unsurprisingly, uncovered a bug in Matrix Brandy.

Will this affect other versions of Brandy (Napoleon Brandy etc.), or is it in an area where you modified the code for Matrix?

I would expect so, the same bug exists in Brandy 1.20.1 (the latest Sourceforge release), I have not tried Napoleon Brandy.

RichardRussell wrote: ↑Tue Jul 16, 2019 5:57 pm

INT was accepting values that were out of range (which is not allowed on the BBC Micro nor RISC OS BBC BASIC implementations).

Those implementations of BBC BASIC (that is up to and including ARM BASIC 5) use 40-bit floats with a 32-bit mantissa. So although the range of integers which can be stored in a floating-point variable is greater than what can be stored in an integer variable (by a factor of two) it's arguable - and indeed Acorn did successfully argue - that it's reasonable to limit the range of values accepted by INT to -2^31 to +2^31-1. If you supply a value outside of this range you get a 'Number too big' error.

However in ARM BASIC 6 and Brandy floating-point variables are 64-bit doubles, which can contain a much larger integer (53-bits rather than 32). In that situation I don't think it's possible to argue that such a restriction is acceptable: you may well want to truncate to an integer a value much larger than 2^31 and the INT function should support doing that.

Here's a simple program to try on any BASIC that has floating-point variables with 64-bits or more:

Code: Select all

```
a = 2^50 + 0.5
b = INT(a)
PRINT a - b
```

This should print '0.5'. If it doesn't I would say something is seriously wrong.

BASIC V gives "Number too big" at the "b=INT(a)" line, and my copy of BASIC64 (ARM BBC BASIC VI (FPA) 1.75, 03 March 2018) gives "Floating point exception: invalid operation" at the same instruction.

### Re: Introduction to BBC BASIC

Posted: **Tue Jul 16, 2019 8:08 pm**

by **RichardRussell**

jahboater wrote: ↑Tue Jul 16, 2019 7:29 pm

I do find it strange that it truncates towards minus infinity rather than zero as is the norm. Is there something mathematical I am missing, because Python division does the same?

The norm? In BASIC it is absolutely standard for the INT() function to truncate towards minus-infinity ('floor'): try it in any BASIC you care to! The BBC rightly insisted that BBC BASIC be standard in this respect. I know of only one BASIC that works differently, Liberty BASIC, and the author acknowledges that it is non-standard.

If you do want to truncate towards zero, which I reiterate is

**not** what INT() should do, then that's easy in BBC BASIC too:

Code: Select all

```
a = INT(b) : REM truncates towards minus infinity
a% = b : REM truncates towards zero (32-bit result)
a%% = b : REM truncates towards zero (64-bit result, BB4W & BBCSDL extension)
```

### Re: Introduction to BBC BASIC

Posted: **Tue Jul 16, 2019 8:12 pm**

by **DavidS**

RichardRussell wrote: ↑Tue Jul 16, 2019 8:08 pm

jahboater wrote: ↑Tue Jul 16, 2019 7:29 pm

I do find it strange that it truncates towards minus infinity rather than zero as is the norm. Is there something mathematical I am missing, because Python division does the same?

The norm? In BASIC it is absolutely standard for the INT() function to truncate towards minus-infinity ('floor'): try it in any BASIC you care to! The BBC rightly insisted that BBC BASIC be standard in this respect. I know of only one BASIC that works differently, Liberty BASIC, and the author acknowledges that it is non-standard.

If you do want to truncate towards zero, which I reiterate is

**not** what INT() should do, then that's easy in BBC BASIC too:

Code: Select all

```
a = INT(b) : REM truncates towards minus infinity
a% = b : REM truncates towards zero (32-bit result)
a%% = b : REM truncates towards zero (64-bit result, BB4W & BBCSDL extension)
```

That norm is only for BASIC implementations that store integers primarily in floating point (like most older MS-BASIC implimentations).

### Re: Introduction to BBC BASIC

Posted: **Tue Jul 16, 2019 8:28 pm**

by **RichardRussell**

DavidS wrote: ↑Tue Jul 16, 2019 8:12 pm

That norm is only for BASIC implementations that store integers primarily in floating point (like most older MS-BASIC implimentations).

I have literally no idea what that means. The way a standard function like INT() behaves obviously should not, and must not, depend on implementation details. In BASIC INT() truncates towards minus infinity; do you know of any non-conforming BASICs except Liberty BASIC?

### Re: Introduction to BBC BASIC

Posted: **Tue Jul 16, 2019 8:29 pm**

by **Heater**

Maybe I'm out of line but I would naturally expect an int function to do the simplest thing and just throw away the bits after the decimal point. Thus producing the closest integer towards zero.

Like Javascript when you do logical operations, that are defined to return 32 bit integer results:

Or C:

Code: Select all

```
int x = -2.3;
int y = -2.7;
printf("%d\n", x);
printf("%d\n", y);
```

Produces:

BASIC is just weird.

### Re: Introduction to BBC BASIC

Posted: **Tue Jul 16, 2019 8:43 pm**

by **RichardRussell**

Heater wrote: ↑Tue Jul 16, 2019 8:29 pm

Maybe I'm out of line but I would naturally expect an int function to do this simplest thing and just throw away the bits after the decimal point. Thus producing the closest integer towards zero.

The most common use to which I put the INT function is in rounding a number to the nearest integer:

Code: Select all

```
nearest_integer = INT(number + 0.5)
```

Thst only works, with both positive and negative numbers, when INT() truncates towards minus-infinity. Without such a function, rounding to the nearest integer is actually quite messy.

BASIC is just weird.

Every competent programming language has that functionality, in C it's called

**floor()** and in BASIC it's called

**INT()**.

Anyway I thought you were the great champion of BASIC being 'standardised'?!

### Re: Introduction to BBC BASIC

Posted: **Tue Jul 16, 2019 8:45 pm**

by **ejolson**

Heater wrote: ↑Tue Jul 16, 2019 8:29 pm

Maybe I'm out of line but I would naturally expect an int function to do this simplest thing and just throw away the bits after the decimal point. Thus producing the closest integer towards zero.

Like Javascript when you do logical operations, that are defined to return 32 bit integer results:

Or C:

Code: Select all

```
int x = -2.3;
int y = -2.7;
printf("%d\n", x);
printf("%d\n", y);
```

Produces:

BASIC is just weird.

You forget Kurz and Kemeny were mathematicians. The greatest integer less than or equal x is a common mathematical function and to them using INT to denote that same function must have seemed natural. More thoughts along these lines were posted

earlier in this thread.

Bugs and weirdness aside, the strange notation in BBC Basic to me is using LOG to stand for base-10 logarithms. This is unique among the Basic dialects I know.

### Re: Introduction to BBC BASIC

Posted: **Tue Jul 16, 2019 8:49 pm**

by **Soruk**

ejolson wrote: ↑Mon Jul 15, 2019 6:38 pm

Code: Select all

```
$ sbrandy
Matrix Brandy BASIC V version 1.21.19 (Linux) 01 Mar 2019
Starting with 651516 bytes free
>
```

You might want to update - 1.21.21 is out, and the git repo has a couple of fixes arising from issues from this thread!

### Re: Introduction to BBC BASIC

Posted: **Tue Jul 16, 2019 8:59 pm**

by **RichardRussell**

ejolson wrote: ↑Tue Jul 16, 2019 8:45 pm

the strange notation in BBC Basic to me is using LOG to stand for base-10 logarithms. This is unique among the Basic dialects I know.

I can't enlighten you on that one; although I was there at the time (1981) I don't recall any discussions on that topic. All I know is that the BBC required of Acorn that BBC BASIC be compatible with the de-facto standard of the day, which was the 8-bit Microsoft BASICs. If you're saying that in those BASICs LOG() performed a natural (Napierian) logarithm it would imply that Acorn failed to meet that requirement, but I don't remember that being raised as an issue then or since.

I expect it was Acorn's decision to include both base-10 and base-e log functions, I'm pretty certain the BBC wouldn't have requested it. In that situation I can see that LOG and LN are sensible function names, to a mathematician, but that can't excuse the incompatibility. Unless somebody can find a contemporary reference it will probably remain a mystery.

### Re: Introduction to BBC BASIC

Posted: **Tue Jul 16, 2019 9:10 pm**

by **Heater**

RichardRussell.

Anyway I thought you were the great champion of BASIC being 'standardised'?!

OK. Far enough.

I don't mind if they all get it wrong, as long as they would all agree with each other.

### Re: Introduction to BBC BASIC

Posted: **Tue Jul 16, 2019 9:16 pm**

by **ejolson**

RichardRussell wrote: ↑Tue Jul 16, 2019 8:59 pm

ejolson wrote: ↑Tue Jul 16, 2019 8:45 pm

the strange notation in BBC Basic to me is using LOG to stand for base-10 logarithms. This is unique among the Basic dialects I know.

I can't enlighten you on that one; although I was there at the time (1981) I don't recall any discussions on that topic. All I know is that the BBC required of Acorn that BBC BASIC be compatible with the de-facto standard of the day, which was the 8-bit Microsoft BASICs. If you're saying that in those BASICs LOG() performed a natural (Napierian) logarithm it would imply that Acorn failed to meet that requirement, but I don't remember that being raised as an issue then or since.

I expect it was Acorn's decision to include both base-10 and base-e log functions, I'm pretty certain the BBC wouldn't have requested it. In that situation I can see that LOG and LN are sensible function names, to a mathematician, but that can't excuse the incompatibility. Unless somebody can find a contemporary reference it will probably remain a mystery.

According to the documentation that comes with bwBASIC the following BASIC dialects used LOG for natural logarithm:

Code: Select all

```
SYNTAX: N = LOG( X )
PARAMETER: X is a number, > 0
DESCRIPTION: The natural logarithm of X; X shall be greater
than zero.
VERSIONS:
[X] BYWATER
[X] BYWATER-2
[X] CALL/360
[X] CBASIC-II
[X] DARTMOUTH
[X] ECMA-55
[X] ECMA-116
[X] GCOS
[X] HAARDT
[X] HANDBOOK1
[X] HANDBOOK2
[X] HEATH
[X] MARK-I
[X] MARK-II
[X] MBASIC
[X] PDP-8
[X] PDP-11
[X] RBASIC
[X] RSTS-11
[X] SYSTEM/360
[X] SYSTEM/370
[X] TRS-80
[X] VINTAGE
[X] XBASIC
```

References for each of these BASIC dialects also appear in the bwBASIC documentation but are too lengthy to post here. Note, there are many other versions of BASIC in the world that use LOG for natural logarithm, the above list is limited to the dialects emulated by bwBASIC.

### Re: Introduction to BBC BASIC

Posted: **Tue Jul 16, 2019 9:57 pm**

by **RichardRussell**

ejolson wrote: ↑Tue Jul 16, 2019 9:16 pm

According to the documentation that comes with bwBASIC the following BASIC dialects used LOG for natural logarithm

I'm not sure of the relevance of that. As I said, the BBC requested of Acorn that BBC BASIC be largely compatible with the 8-bit Microsoft BASICs of the day, so what other BASICs may or may not have done then or since really doesn't have any bearing. I have asked a question at the StarDot forum to see if anybody can shed any light on the apparent lack of compatibility you have drawn attention to, but after 38 years it will be understandable if nobody can. There's no evidence that it has dented BBC BASIC's popularity!

### Re: Introduction to BBC BASIC

Posted: **Tue Jul 16, 2019 11:22 pm**

by **DavidS**

Heater wrote: ↑Tue Jul 16, 2019 6:15 pm

Wow, my humble Fibo challenge seems to have been doing a great job of shaking out the bugs in various language run-times. I hope they are all getting reported and fixed so that this has not been entirely a waste of time.

That has definitely been true.

Though in this particular case it is not a bug at all. In Richard Russells BBC BASIC he allows for 64-bit integers, so the behaviour is reasonable. In BBC BASIC 6 (BBC BASIC V with 64-bit floats) it is following the definition of the language, which says that INT floors to the integer and that the integer must fit in the languages integer variable type.

Now the issue with Brandy BASIC is quite a surprise.

### Re: Introduction to BBC BASIC

Posted: **Tue Jul 16, 2019 11:32 pm**

by **DavidS**

ejolson wrote: ↑Mon Jul 15, 2019 7:05 pm

DavidS wrote: ↑Mon Jul 15, 2019 7:04 pm

Same results using either LOG or LN.

Did you try the Matrix Brandy Basic code just posted above?

Yes I did, and unsurprisingly the results are the same.

Code: Select all

```
*BASIC64 -quit BRDFIBO
LINE : 8550 ERROR : Invalid arithmetic operation
*BASICVFP -quit BRDFIBO
LINE : 8550 ERROR : Invalid arithmetic operation
*BASIC -quit BRDFIBO
LINE : 8550 ERROR : Number too big
*
```

Though I did add the error check line 10 so I could get the error accurately:

Code: Select all

```
10 : ON ERROR PRINT "LINE : " + STR$(ERL) + " ERROR : " + REPORT$ : END
100 ...
```

### Re: Introduction to BBC BASIC

Posted: **Wed Jul 17, 2019 2:17 am**

by **DavidS**

Soruk wrote: ↑Tue Jul 16, 2019 4:58 pm

This has, unsurprisingly, uncovered a bug in Matrix Brandy. INT was accepting values that were out of range (which is not allowed on the BBC Micro nor RISC OS BBC BASIC implementations).

INT was being implemented as casting the float to a 32-bit int, which happened to get the sign right and work on a RasPi, but failed spectactularly on x86 (32-bit and 64-bit). Lines 8520 and 8600 inclusively should be removed, and in its place, add:

Also, line 241 should be removed, really it should crash the interpreter but for some reason it isn't! I need to check on that......

Givin those changes it works on RISC OS BBC BASIC V and BBC BASIC 6.

Would likely also work with with &FFFFFFFF, as BBC BASIC On RISC OS supports unsigned values in integers.

### Re: Introduction to BBC BASIC

Posted: **Wed Jul 17, 2019 6:03 am**

by **ejolson**

RichardRussell wrote: ↑Tue Jul 16, 2019 9:57 pm

ejolson wrote: ↑Tue Jul 16, 2019 9:16 pm

According to the documentation that comes with bwBASIC the following BASIC dialects used LOG for natural logarithm

I'm not sure of the relevance of that. As I said, the BBC requested of Acorn that BBC BASIC be largely compatible with the 8-bit Microsoft BASICs of the day, so what other BASICs may or may not have done then or since really doesn't have any bearing. I have asked a question at the StarDot forum to see if anybody can shed any light on the apparent lack of compatibility you have drawn attention to, but after 38 years it will be understandable if nobody can. There's no evidence that it has dented BBC BASIC's popularity!

The original goal of bwBasic was to be compatible with early versions of Microsoft Basic running on the MITS Altair. That project expanded to include a whole bunch of other Basic dialects. For example, MBASIC was a Microsoft written Basic that ran under XENIX and TRS-80 LBASIC is a third-party extension to the ROM Basic written by Microsoft.

Another Microsoft Basic appeared in the Commodore PET, CBM and C64 machines. There is an interesting project

here that reverse compiled the C64 binary to produce portable C that can be recompiled on any Linux computer. The result is

Code: Select all

```
**** COMMODORE 64 BASIC V2 ****
64K RAM SYSTEM 38911 BASIC BYTES FREE
READY.
PRINT LOG(10)
2.30258509
READY.
X=1E15:Y=INT(X):IF X=Y THEN PRINT "EQUAL"
EQUAL
READY.
```

This indicates that LOG represents the natural logarithm in the C64 version of Microsoft Basic as well.

It would be interesting if anyone knows why the designers of BBC Basic chose to break with tradition and defined LOG as the base-10 logarithm. It certainly contributes to the general mayhem where every Basic is slightly different, but I suspect your are right that this incompatibility had no effect on the popularity of BBC Basic. In fact, it's pretty easy to argue that BBC Basic became popular enough to be its own standard.

### Re: Introduction to BBC BASIC

Posted: **Wed Jul 17, 2019 6:48 am**

by **Soruk**

DavidS wrote: ↑Wed Jul 17, 2019 2:17 am

Would likely also work with with &FFFFFFFF, as BBC BASIC On RISC OS supports unsigned values in integers.

No. The top bit is the sign. &FFFFFFFF=-1

**Edit:** As Richard Russell pointed out quite correctly, what I wrote is true for integer variables - and hexadecimal conversions. However, you can (using decimal) store a larger integer in a float variable.

On a BBC Micro, a RiscPC in BASIC 6 and Matrix Brandy, the following all give these results:

Code: Select all

```
>@%=10
>A=&FFFFFFFF
>PRINT A
-1
>A=4294967295
>PRINT A
4294967295
>_
```

### Re: Introduction to BBC BASIC

Posted: **Wed Jul 17, 2019 7:06 am**

by **Heater**

ejolson,

It would be interesting if anyone knows why the designers of BBC Basic chose to break with tradition and defined LOG as the base-10 logarithm.

I have no idea but I can guess...

Every schoolboy (At least in England at the time) knows that LOG refers to the base 10 logarithm. Anyone old enough to be building computers at that time probably used books of log tables in school. Which were base 10. Unless they stayed at school past leaving age, 15 at the time, said schoolboys had likely never heard of natural logarithms. But if they did they knew that natural logs were referred to by "ln" in their maths class.

So I imagine it was simply done so as not to confuse school kids. If anyone thought about it at all, which like they did not. I mean why would they?

Speaking of tradition, sadly I don't recall what kind of log "LOG" was in the basic we used via teletype and acoustically coupled modem back in 1973.

### Re: Introduction to BBC BASIC

Posted: **Wed Jul 17, 2019 7:29 am**

by **PeterO**

Algol-60 used "ln()" for natural log.

PeterO

### Re: Introduction to BBC BASIC

Posted: **Wed Jul 17, 2019 8:18 am**

by **RichardRussell**

DavidS wrote: ↑Tue Jul 16, 2019 11:22 pm

In BBC BASIC 6 (BBC BASIC V with 64-bit floats) it is following the definition of the language, which says that INT floors to the integer and that the integer must fit in the languages integer variable type.

You really can't excuse an undesirable feature on the grounds that it follows "the definition of the language"! OK you can say that in those circumstances it should not be called a bug, but that doesn't make it right. Think about what one might actually want to do with the language: if it supports up to 53-bit integers (as ARM BASIC 6 and Brandy do) then there are going to be circumstances when one wants to truncate a non-integral value to such an integer, and the function that BASIC provides for this is INT().

Presumably you acknowledge that the functionality that my little program illustrated - truncating the value

**2^50+0.5** to an integer - is a reasonable thing to want to do. How then would you code it in ARM BASIC 6?

### Re: Introduction to BBC BASIC

Posted: **Wed Jul 17, 2019 8:21 am**

by **Soruk**

Sinclair Spectrum BASIC (at least on the 48K) has a LN function (which uses base e) - but no LOG function.

### Re: Introduction to BBC BASIC

Posted: **Wed Jul 17, 2019 8:25 am**

by **Soruk**

RichardRussell wrote: ↑Wed Jul 17, 2019 8:18 am

if it supports up to 53-bit integers (as ARM BASIC 6 and Brandy do)

Unless I'm doing something wrong, they don't.

In BASIC 6 on my RiscPC (RPCEmu), I did (and got):

Code: Select all

```
>a%=2^32
Floating point exception: invalid operation
>_
```

### Re: Introduction to BBC BASIC

Posted: **Wed Jul 17, 2019 8:30 am**

by **RichardRussell**

ejolson wrote: ↑Wed Jul 17, 2019 6:03 am

It would be interesting if anyone knows why the designers of BBC Basic chose to break with tradition and defined LOG as the base-10 logarithm.

I've received a couple of answers at StarDot:

"

*The original MS 1978 BASIC did indeed only support log base-e with the LOG keyword. This version was licensed to Commodore and made it into the VIC 20 and C64. However, my first machine was an Oric 1, which also had a MS variant BASIC, but had both LOG and LN keywords. Meanwhile, Sinclair BASIC only had the LN keyword*".

"

*For decades LOG has meant base-10 and LN has meant natural/base-e. My mid-'70s HP calculator has buttons for ln and log which give natural and base-10 respectively, as does my mid-'80s Casio Scientific*."

So, given that the BBC was very much influenced by advice received from educational experts at the time, I wouldn't be at all surprised if it was a deliberate departure from the Microsoft standard in the interests of mathematical convention and compatibility with pocket calculators. There may even have been requests from teachers for the change if they were encountering confusion in the classroom.

### Re: Introduction to BBC BASIC

Posted: **Wed Jul 17, 2019 8:32 am**

by **jahboater**

RichardRussell wrote: ↑Tue Jul 16, 2019 8:43 pm

The most common use to which I put the INT function is in rounding a number to the nearest integer:

Code: Select all

```
nearest_integer = INT(number + 0.5)
```

That only works, with both positive and negative numbers, when INT() truncates towards minus-infinity. Without such a function, rounding to the nearest integer is actually quite messy.

BASIC needs a ROUND(x) function:-

trunc( copysign( fabs(x) + 0.5, x )

ARM floating point has an instruction for just that (frinta).

As for log(x), I do hope exp(x) does 10.0^x to match.

### Re: Introduction to BBC BASIC

Posted: **Wed Jul 17, 2019 8:50 am**

by **RichardRussell**

Soruk wrote: ↑Wed Jul 17, 2019 8:25 am

RichardRussell wrote: ↑Wed Jul 17, 2019 8:18 am

if it supports up to 53-bit integers (as ARM BASIC 6 and Brandy do)

Unless I'm doing something wrong, they don't.

You are trying to load the number into an integer-type variable

**a%**. Obviously that is going to fail, because integer

**variables** can hold only 32-bit integers. But ordinary (non % suffix) variables can hold integers up to 53-bits; the size of integer that can be contained in a 'floating point' variable depends on the number of bits in the mantissa.

Even in 8-bit BBC BASICs and ARM BASIC 5 an ordinary variable like

**a** can contain a wider range of integers than an integer variable like

**a%** can, but the increase is only a factor of two. The range of integers that can be held in

**a%** is -2147483648 to +2147483647 whereas the range of integers that can be held in

**a** is -4294967296 to +4294967296!

Don't fall into the trap of equating 'integer variable' (which is a particular data type) with 'integer' (which is a mathematical concept meaning 'whole number').

*Edit*: Just to prove the point (not that I was in any doubt) you can run this on the original BBC Micro:

Code: Select all

```
@%=10
FOR A = -4294967296 TO -4294967280
PRINT A
NEXT
```