Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 09:43 20 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 : [MMBasic]Mathematical Precision

Author Message
G8JCF

Guru

Joined: 15/05/2014
Location: United Kingdom
Posts: 676
Posted: 07:17am 16 May 2014
Copy link to clipboard 
Print this post

In the "MMBasic Language Manual" in the implementation characteristics is says

"Numbers are stored and manipulated as single precision floating point numbers. The maximum number that can be represented is 3.40282347e+38 and the minimum is 1.17549435e-38"

and shows 9 digit precision. When I run MMBasic itself, either in DOS or on a Micromite the most I ever see is 6 digits of precision, try PRINT1/7 for example

Can someone tell me please if 6 digit precision is correct, and/or is there a way to see more precision ?

Reason for asking is that I'm trying to do calculations in MHz to 1 Hz precision,
eg LET FREQ=12345678 'Frequency in Hz
PRINT FREQ
1.23457e+07 'Displayed in response to the PRINT statement

Many thanks

PeterEdited by G8JCF 2014-05-17
The only Konstant is Change
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3678
Posted: 08:52am 16 May 2014
Copy link to clipboard 
Print this post

9 digits would be about 30 bits (*) and for PIC32 single precision fp of 32 bits that sounds unlikely.

But some MHz meaning millions would only be 7 digits (or so) and should be OK.

I think it just uses the format that's more or less native to the chip so the Mchp doc should give details.

PRINT will be using some default format / rounding / etc. Is STR$ or whatever that new thing is any good? Or write a test program but with a bit of thought LOL

(*) because 10^3 is about 2^10 and 10^9 is about 2^30

JohnEdited by JohnS 2014-05-17
 
G8JCF

Guru

Joined: 15/05/2014
Location: United Kingdom
Posts: 676
Posted: 11:17am 16 May 2014
Copy link to clipboard 
Print this post

Hi John

Thanks for the reply, I need to deal with MHz up to 40,000,000 hence 8 digits.

I've come across TassyJim's BigInt program so I might spend some time optimising that for improved speed.

I was just curious that since the manual showed 9 digit precision that perhaps there was some really clever trick which I just hadn't found - I tried STR$ but to no avail.

2^31 is 2147483648 is 9 digits, but there doesn't seem to be a LONG or INT32 data type in MMBasic, if there was then by judicious scaling one can do all integer arithmetic and maintain high precision.

Anyway, thanks for taking the time to explain.

73

Peter
The only Konstant is Change
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3678
Posted: 12:33pm 16 May 2014
Copy link to clipboard 
Print this post

Apparently always stored in one way, single fl.pt.

Might manage 4E7 without loss of precision. Try it...

John
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5923
Posted: 02:30pm 16 May 2014
Copy link to clipboard 
Print this post

You can use FORMAT$ to prevent the display from defaulting to exponential format.

FREQ=12345678 'Frequency in Hz
PRINT FREQ
print format$(freq,"%9.0f")


You will still be limited by the precision of 32 bit floating point.
I would split the number into Hz, kHz, MHz if possible and then put the strings together for display.

The biggest integer is 16777100 so if you can live with 10Hz precision 40 MHz is achievable without splitting numbers although you will have to watch any maths which could easily loose precision.

My BigInts program is very slow and one day I will try to produce a faster version probably by working in thousands instead of single digits.

Jim
VK7JH
MMedit   MMBasic Help
 
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 2294
Posted: 10:33pm 17 May 2014
Copy link to clipboard 
Print this post

this could be an interesting point to ask a question of geoff: how difficult would it be to recompile the various versions of mmbasic to use turbo pascal style 6-byte reals? this would give 11-digits of decimal precision, as well as encompassing 36-bit integers. internally one would then do conversions to handle as 8-byte ieee reals within the interpreter.

or one could go for 8-byte ieee reals throughout, for 15 digits of decimal precision and to encompass 48-bit integers.

this is more of a hypothetical question, as aside from the type change, i'm quite sure the associated C libraries would likely blow out the flash budgets on both micromite and maximite.

another interesting option would be to add a purely integer data type, where an integer is specified with a "%" sign as the last character of the variable name, ie:

ABC% = 12345

this would then allow for 32-bit integers, or one could be extravagant and go for 48 or 64-bits with 6 or 8 bytes per integer.


rob :-)Edited by robert.rozee 2014-05-19
 
G8JCF

Guru

Joined: 15/05/2014
Location: United Kingdom
Posts: 676
Posted: 06:15am 18 May 2014
Copy link to clipboard 
Print this post

Hi

32 bit Unsigned Integers would be really convenient especially for a 32 bit processor.

I don't think the FORMAT$ keyword exists for the Micromite version of MMBasic.

I've started writing a BigInteger library of my own, and thus far have coded up AddBig and MulBig (these are the easy ones of course !), DivBig is the really tough one, followed by SubBig. Here's AddBig to give you all a taste of the methods I'm using

'*********************************************************** *
'Add 2 x 12 digit integers. Result is a 13 Digit integer
'
'*********************************************************** *
Function AddBig$(a$,b$)

Local A(12),B(12),C(13),I,J,C$(1) length 13

'Split A$ into A()
J=0
for I=Len(a$) to 1 step -1
A(J)=val(Mid$(A$,I,1))
J=J+1
next I

'Split B$ into B()
J=0
for I=Len(B$) to 1 step -1
B(J)=val(Mid$(B$,I,1))
J=J+1
next I

Local Carry
Carry=0
'Add each element of A() to B() result into c()
For I = 0 to 11
C(I)=A(I) + B(I) + Carry
if C(I)>9 then
Carry=1
C(I)=c(I)-10
else
Carry=0
endif
Next I

C(12)=Carry

For I=12 to 0 step -1
c$(1)=c$(1) + str$(c(I))
next

AddBig$=TrimLZero$(C$(1))

End Function

Function TrimLZero$(A$)

local I
for I= 1 to Len(A$)

If Mid$(A$,I,1)<>"0" then
TrimLZero$= Mid$(A$,I)
exit function
endif

next I

TrimLZero$="0"

end function


Thanks for all the ideasEdited by G8JCF 2014-05-19
The only Konstant is Change
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5923
Posted: 05:15pm 18 May 2014
Copy link to clipboard 
Print this post

The micromite alternative for the FORMAT$ command is STR$
Not a full equivalent by has the necessary options for this purpose.

Jim

VK7JH
MMedit   MMBasic Help
 
G8JCF

Guru

Joined: 15/05/2014
Location: United Kingdom
Posts: 676
Posted: 06:26am 31 May 2014
Copy link to clipboard 
Print this post

Hi TassyJim

Further to your comments I've coded up MulBig to work in chunks of 3 decimal digits at a time which as you suggested makes it much, much faster. 3 Digits at a time is the maximum number which preserves full precision across the full range of numbers, eg 99,999,999 x 9,999,999,999. Anyway in case someone else needs long precision Multiplication here's the source


'
'Returns A$ x B$ as a string
'Usage A$="12345678", B$="1234"
'C$=MulBCD$(A$,B$)
'This algorithm works on Triplets of digits
'
Function MulBCD$(A$, B$)
Local Cy, I, J, K, L, M, N

'Arrays into which we will unpack the BCD numbers
Local A1(4), B1(4)

'Arrays for the answers
Local D(12), C1(8)

Local C$(1) Length 3, C2$(1) Length 24

Local A2$(1) Length 12, B2$(1) Length 12

M = Len(A$)
N = Len(B$)

'Optimise the speed by making sure the Multiplier is the shorter of the
'2 arguments
If N > M Then
A2$(1) = B$
B2$(1) = A$
Else
A2$(1) = A$
B2$(1) = B$
EndIf

M = Len(A2$(1))
N = Len(B2$(1))

'Are the numbers in multiples of 3 digits
J = 0
If M Mod 3 <> 0 Then
For I = 3 To 12 Step 3
If M < I Then
J = I - M
M = I
Exit For
EndIf
Next I
EndIf
A2$(1) = String$(J, "0") + A2$(1)

'Are the arguments in multiples of 3 digits
J = 0
If N Mod 3 <> 0 Then
For I = 3 To 12 Step 3
If N < I Then
J = I - N
N = I
Exit For
EndIf
Next I
EndIf

B2$(1) = String$(J, "0") + B2$(1)

'Unpack the Numbers from String into Numeric array
J = 0
For I = M - 2 To 1 Step -3
A1(J) = Val(Mid$(A2$(1), I, 3))
J = J + 1
Next I

J = 0
For I = N - 2 To 1 Step -3
B1(J) = Val(Mid$(B2$(1), I, 3))
J = J + 1
Next I

'Now Do the Long Multiplication of the two numbers
'Set Units first
L = 0
K = 0

For I = 0 To M \ 3 Step 1
Cy = 0
For J = 0 To N \ 3 Step 1

C1(J) = (A1(I) * B1(J)) + Cy

If C1(J) > 999 Then
Cy = C1(J) \ 1000
C1(J) = C1(J) Mod 1000
Else
Cy = 0
EndIf

Next J

'Add the partial result to the overall total
'Add each element of C() to D() result into D()
Cy = 0

For J = 0 To 23 \ 3
K = J + L
D(K) = D(K) + C1(J) + Cy
If D(K) > 999 Then
Cy = D(K) \ 1000 '100
D(K) = D(K) Mod 1000 '- 1000
Else
Cy = 0
EndIf
Next J

L = L + 1

Next I

'Build result string
For I = 23 \ 3 To 0 Step -1
C$(1)=""
If D(I) < 100 Then C$(1)="0"
If D(I) < 10 then C$(1)="00"
C2$(1) = C2$(1) + C$(1)+(Str$(D(I)))
Next I

C2$(1) = TrimL$(C2$(1), "0")
MulBCD$=C2$(1)

End Function


I hope someone finds this useful !

73

Peter (GM8JCF)
The only Konstant is Change
 
G8JCF

Guru

Joined: 15/05/2014
Location: United Kingdom
Posts: 676
Posted: 10:04am 31 May 2014
Copy link to clipboard 
Print this post

Sorry, I forgot to include TrimL$


'====================================
'
'Remove leading CHARacters from a string
'If char$ is ommitted or blank then trim ZEROES
'
Function TrimL$(A$, Char$)

Local I, CH$(1) Length 1

ch$(1) = Left$(Char$, 1)
If ch$(1) = "" Then ch$(1) = "0"
For I = 1 To Len(A$)

If Mid$(A$, I, 1) <> "0" Then
TrimL$ = Mid$(A$, I)
Exit Function
EndIf

Next I

TrimL$ = CH$(1)

End Function

The only Konstant is Change
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5923
Posted: 02:19pm 31 May 2014
Copy link to clipboard 
Print this post

Thanks for that Peter.
It was something I was going to have to do soon.

Jim

VK7JH
MMedit   MMBasic Help
 
Print this page


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

© JAQ Software 2024