View Full Version : weak ascii to extended format conversion and val anomalies
just posted to the support forum but it seems it vanished!
anyway, ThinBasic seems to be weak at converting strings to the extended number format,
here's an example that points out the difference between ThinBasic and the Windows CRT Function atoldbl which does pretty good at converting a string to extended number, note that in the example only the least significant word is printed wchich is where the differences lie.
perhaps I am missing a number suffix?
Uses "console"
Union myext
x As Ext
m(5) As Word
End Union
Declare Function atoldbl CDECL Lib "msvcrt.dll" Alias "_atoldbl" (ByRef x As Ext, ByVal str As String) As Long
Dim i As Long
Dim As myExt C(13)
c( 1).x = 0.0416666666666666666666666666666667
c( 2).x = 0.0375000000000000000000000000000000
c( 3).x = 0.397464726631393298059964726631393
c( 4).x = 0.421820406579914409892038527385284
c( 5).x = 1.32617714549352866190567230645777
c( 6).x = 1.24665196134022087534323346104365
c( 7).x = 2.81748740120023757492990746021309
c( 8).x = 2.50801225997617111696244989421908
c( 9).x = 4.88443581575683122522389821984201
c(10).x = 4.19318163088605289959023955536177
c(11).x = 7.54769682270671300925924871225142
c(12).x = 6.28168645377651932511394974053960
c(13).x = 10.8385202432614643498425499777578
Dim As myExt Pi1
Dim As myExt Pi2
Pi1.x = 3.1415926535897932384626433832795
atoldbl(Pi2.x, "3.1415926535897932384626433832795")
Dim As myExt d(13)
atoldbl(d( 1).x, "0.0416666666666666666666666666666667")
atoldbl(d( 2).x, "0.0375000000000000000000000000000000")
atoldbl(d( 3).x, "0.397464726631393298059964726631393")
atoldbl(d( 4).x, "0.421820406579914409892038527385284")
atoldbl(d( 5).x, "1.32617714549352866190567230645777")
atoldbl(d( 6).x, "1.24665196134022087534323346104365")
atoldbl(d( 7).x, "2.81748740120023757492990746021309")
atoldbl(d( 8).x, "2.50801225997617111696244989421908")
atoldbl(d( 9).x, "4.88443581575683122522389821984201")
atoldbl(d(10).x, "4.19318163088605289959023955536177")
atoldbl(d(11).x, "7.54769682270671300925924871225142")
atoldbl(d(12).x, "6.28168645377651932511394974053960")
atoldbl(d(13).x, "10.8385202432614643498425499777578")
Console_WriteLine "ThinBasic atoldbl hex-difference value-difference"
Console_Write " "+RSet$(Hex$(Pi1.m(1)),4 Using "0")+" "+RSet$(Hex$(Pi2.m(1)),4 Using "0")+" "+RSet$(Hex$(Pi2.m(1)-Pi1.m(1)),4 Using "0")+" "
Console_WriteLine Using$("##.#####^^^^",Pi1.x-Pi2.x)
For i=1 To 13
Console_Write " "+RSet$(Hex$(c(i).m(1)),4 Using "0")+" "+RSet$(Hex$(d(i).m(1)),4 Using "0")+" "+RSet$(Hex$(d(i).m(1)-c(i).m(1)),4 Using "0")+" "
Console_WriteLine Using$("##.#####^^^^",c(i).x-d(i).x)
Next
Console_WriteLine "All done. Press any key to finish"
Console_WaitKey
also the ThinBasic Val Function gives a single when given "1e4932"
note also that the constants M_PI and M_E are defined as Double. :)
ErosOlmi
22-08-2011, 07:49
just posted to the support forum but it seems it vanished!
No, it is not vanished: http://www.thinbasic.com/community/project.php?issueid=304
It is issue ID 304.
As you know thinBasic is developed using PowerBasic compiler. So this mainly connects to the fact that is PB behaves in a certain way regarding a very specific area (like converting strings to number and the other way round), more or less tB will behave the same.
That said, I reported the "1e4932" conversion behave to PB support (and I know others has done) and the reply I got was:
Hi Eros,
That number effectively evaluates to positive infinity. Because of the nature of most PowerBASIC users, we do not attempt to process infinity in numerical expressions. Therefore, when it occurs, we translate an approximation of the maximum value that can be stored in a single precision float. This avoids the issue of hardware floating-point exceptions on the FPU. At a later date it is possible we will handle infinity deferentially, but to date, we have had negligible interest for the type of application that our customers typically create.
Sincerely,
Jeff Daniels
PowerBASIC Staff
On 08/08/2011 6:59 PM, Eros Olmi (thinBasic) wrote:
> Dear support,
>
> I'm not an expert in "inside" extended numbers so please excuse me if I post a dummy question but documentation reports that the max EXT number is 1.2*10^4932
>
> If I compile and execute the below code it seems that "MsgBox Str$(Val("1e+4932"), 18)" is failing something.
>
> Regards
> Eros
>
> '---[Code start]----------------------------------------------
> Function PBMain() As Long
>
> Dim myNumber As Ext
> myNumber = 10 ^ 4932
>
> MsgBox Str$(myNumber, 18)
>
> MsgBox Str$(Val("1e+4932"), 18) '---It returns 1.7014118346046923E+38
>
> MsgBox Str$(Val("1e+4931"), 18)
>
> End Function
> '---[Code end]----------------------------------------------
What this means is that for the moment we have to survive or apply a trick inside thinBasic.
This also means that in future maybe there will be a different behave.
Ciao
Eros
Hi Eros :)
does ThinBasic support suffixes for the number type like PowerBasic?
I think double is one # and extended is two ##, I think that in my haste in testing using PowerBasic forgot to add the proper suffix.
I will edit the first post so as not to harm the innocent.
adding siffixes does not make any difference in the result, here's the test, maybe somebody will spot an error in my code.
#COMPILE EXE
#DIM ALL
UNION myext
x AS EXT
m(4) AS WORD
END UNION
DECLARE FUNCTION atoldbl CDECL LIB "msvcrt.dll" ALIAS "_atoldbl" (BYREF x AS EXT, BYVAL str AS STRING) AS LONG
FUNCTION PBMAIN () AS LONG
DIM i AS LONG
DIM C(13) AS myExt
c( 1).x = 0.0416666666666666666666666666666667##
c( 2).x = 0.0375000000000000000000000000000000##
c( 3).x = 0.397464726631393298059964726631393##
c( 4).x = 0.421820406579914409892038527385284##
c( 5).x = 1.32617714549352866190567230645777##
c( 6).x = 1.24665196134022087534323346104365##
c( 7).x = 2.81748740120023757492990746021309##
c( 8).x = 2.50801225997617111696244989421908##
c( 9).x = 4.88443581575683122522389821984201##
c(10).x = 4.19318163088605289959023955536177##
c(11).x = 7.54769682270671300925924871225142##
c(12).x = 6.28168645377651932511394974053960##
c(13).x = 10.8385202432614643498425499777578##
DIM Pi1 AS myExt
DIM Pi2 AS myExt
Pi1.x = 3.1415926535897932384626433832795##
atoldbl(Pi2.x, "3.1415926535897932384626433832795")
DIM d(13) AS myExt
atoldbl(d( 1).x, "0.0416666666666666666666666666666667")
atoldbl(d( 2).x, "0.0375000000000000000000000000000000")
atoldbl(d( 3).x, "0.397464726631393298059964726631393")
atoldbl(d( 4).x, "0.421820406579914409892038527385284")
atoldbl(d( 5).x, "1.32617714549352866190567230645777")
atoldbl(d( 6).x, "1.24665196134022087534323346104365")
atoldbl(d( 7).x, "2.81748740120023757492990746021309")
atoldbl(d( 8).x, "2.50801225997617111696244989421908")
atoldbl(d( 9).x, "4.88443581575683122522389821984201")
atoldbl(d(10).x, "4.19318163088605289959023955536177")
atoldbl(d(11).x, "7.54769682270671300925924871225142")
atoldbl(d(12).x, "6.28168645377651932511394974053960")
atoldbl(d(13).x, "10.8385202432614643498425499777578")
PRINT "PowerBasic atoldbl difference"
PRINT " "+RSET$(HEX$(Pi1.m(0)),4 USING "0")+" "+RSET$(HEX$(Pi2.m(0)),4 USING "0")+" "+RSET$(HEX$(Pi2.m(0)-Pi1.m(0)),4 USING "0")+" ";
PRINT USING$("##.#####^^^^",Pi1.x-Pi2.x)
FOR i=1 TO 13
PRINT " "+RSET$(HEX$(c(i).m(0)),4 USING "0")+" "+RSET$(HEX$(d(i).m(0)),4 USING "0")+" "+RSET$(HEX$(d(i).m(0)-c(i).m(0)),4 USING "0")+" ";
PRINT USING$("##.#####^^^^",c(i).x-d(i).x)
NEXT
PRINT "All done. Press any key to finish"
WAITKEY$
END FUNCTION
That number effectively evaluates to positive infinity.
Eros, that's bull, can't believe they would accually say it, here's proof.
#COMPILE EXE
#DIM ALL
DECLARE FUNCTION atoldbl CDECL LIB "msvcrt.dll" ALIAS "_atoldbl" (BYREF x AS EXT, BYVAL str AS STRING) AS LONG
FUNCTION PBMAIN () AS LONG
DIM x AS EXT
atoldbl(x, "1e4932")
PRINT "the string "+CHR$(34)+"1e4932 "+CHR$(34)+" converted to extended value = ";x
PRINT "All done. Press any key to finish"
WAITKEY$
END FUNCTION
danbaron
23-08-2011, 07:32
I don't know exactly what you guys are talking about.
I don't have time now.
Here is what I found.
Dan
' code --------------------------------------------------------------------------------------
Uses "console"
Dim x,y As Ext
x = Val("1e4932")
y = Val("9.99999999999999999999e4931")
PrintL x
PrintL y
WaitKey
'output -------------------------------------------------------------------------------------
1.70141183460469232E+38
9.99999999999999999E+4931
Petr Schreiber
23-08-2011, 09:26
Hi Jack,
I don't think ThinBASIC supports suffixes like PB does. To force precision, there is different mechanism involved:
a = (1.1234567890) As Single
The atoldbl functions is interesting, maybe it could be used to handle number parsing in ThinBASIC? (in cases other than binary/hex).
Petr
ErosOlmi
23-08-2011, 09:48
The atoldbl functions is interesting, maybe it could be used to handle number parsing in ThinBASIC? (in cases other than binary/hex).
That function is part of Microsoft C runtime and (even if it should be present in mainly all computers) I prefer not to create such a dependancy.
thanks Petr for the tip :)
Eros, I have done some work on floating point conversion and could without much work
translate the FreeBasic code to PowerBasic, which you and others could test out and improve,
the code is in the public domain and there are no licensing restrictions at all.
I don't know exactly what you guys are talking about.
Dan, what we are talking about is the lack of precision of PowerBasic string to extended number conversion, for example
the value in hexadecimal of Pi starting with the exponent and then the most significant to the least significand word of the mantissa is
4000 C90F DAA2 2168 C234 C4C6
note the bald extra word, Pi rounded up is:
4000 C90F DAA2 2168 C235
but PowerBasic gives
4000 C90F DAA2 2168 C20E
so efectivly, PowerBasic only converts a literal or string to about 56 bits of precision instead of 64 bits.
in the example above only the least significant word of the mantissa is printed.
danbaron
24-08-2011, 07:26
In thinBasic.
' code ----------------------------------------------------------------------------------------
Uses "console"
Dim pi1, pi2, pi3 As Ext
Dim s0, s1, s2, s3 As String
%pi0 = 3.14159265358979323846264338327 As Ext
pi1 = 3.14159265358979323846264338327
s2 = "3.14159265358979323846264338327"
pi2 = Val(s2)
pi3 = 4*Atn(1)
s0 = Format$(%pi0, "0.000000000000000000000000000000000000000")
s1 = Format$(pi1, "0.000000000000000000000000000000000000000")
s2 = Format$(pi2, "0.000000000000000000000000000000000000000")
s3 = Format$(pi3, "0.000000000000000000000000000000000000000")
PrintL s0
PrintL s1
PrintL s2
PrintL s3
WaitKey
' output --------------------------------------------------------------------------------------
3.141592653589793230000000000000000000000
3.141592653589793230000000000000000000000
3.141592653589793230000000000000000000000
3.141592653589793240000000000000000000000
Petr Schreiber
24-08-2011, 08:38
so efectivly, PowerBasic only converts a literal or string to about 56 bits of precision instead of 64 bits.
The Extended precision is documented to have 18 digits of precision. I guess numbers going after that are just cut out.
I will contact the support about it - because for SINGLE and DOUBLE the correct rounding takes place indeed.
Maybe it is some optimization, maybe for SINGLE and DOUBLE the number is parsed as EXT (natively supported on CPU) and then "decimated" to SINGLE/DOUBLE, but as there is not anything bigger than EXT in hardware, there is no higher precision number to decimate back to EXT. Just a wild guess, and maybe complete nonsense from my side :)
Petr