I'm using PB versions Win x64 v6.21 & v6.3b2, but the performance has been an issue for years looking at historical posts.With which version of PB?
Why are ValF & ValD so slow?
Re: Why are ValF & ValD so slow?
Re: Why are ValF & ValD so slow?
Don't you have a check for letters at the end of a fraction?
Code: Select all
Debug _ValD(@"1.1a")
Re: Why are ValF & ValD so slow?
No, I checked characters before and after an integer, but not a fractional number - I've added that one now, thanks.AZJIO wrote: Wed Oct 01, 2025 2:56 pmDon't you have a check for letters at the end of a fraction?Code: Select all
Debug _ValD(@"1.1a")
Re: Why are ValF & ValD so slow?
Code: Select all
Debug _ValD(@"1.1.1") ; 1.11 ?
Debug _ValD(@"1.1.1.1.1") ; 1.1111 ?
Re: Why are ValF & ValD so slow?
Lots of edge cases, added, thanks.AZJIO wrote: Wed Oct 01, 2025 3:49 pmCode: Select all
Debug _ValD(@"1.1.1") ; 1.11 ? Debug _ValD(@"1.1.1.1.1") ; 1.1111 ?
Re: Why are ValF & ValD so slow?
That's why I suggested atof() or equivalent wtof().
I don't have ValD() in many high speed scenarios but thanks for this post. I will check my code.
I don't have ValD() in many high speed scenarios but thanks for this post. I will check my code.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Re: Why are ValF & ValD so slow?
I added an exponential format analyzer and increased the speed.
pjay
This speeds up for digits 0-9, but slows down for other numbers. Since ValD() works with fractional numbers, the 0-9 range does not have a high priority.
Without creating a variable:
This code is dangerous:
If endChar is not present in the string, an infinite loop can occur. To avoid this, you should also check that the value in the pointer is not Null
Code: Select all
EnableExplicit
DisableDebugger
#SzChar = SizeOf(Character) ; =2
; an improvement from the STARGÅTE
Procedure.d Pow2(n, replay)
Protected result.d = 1, bit = 1<<8 ; most significant bit, 256, enough for double exponent
If replay > 308
ProcedureReturn Infinity()
EndIf
While replay & bit = 0 And bit ; Searching the most significant bit
bit >> 1
Wend
While bit > 0
result * result
If replay & bit
result * n
EndIf
bit >> 1
Wend
ProcedureReturn result
EndProcedure
Procedure.d ValD2(*c.Character)
Protected negative, decimal, exponent, negative2 ; , pos
Protected divider = 1
Protected result.d
; Protected *pLong.long = *c
If *c = 0 Or *c\c = 0
ProcedureReturn NaN() ; Or 0?
EndIf
While *c\c = ' ' Or *c\c = ' '
*c + #SzChar
Wend
; If *pLong\l = 6357070 And CompareMemory(*c, @"NaN", 6)
; ProcedureReturn NaN()
; EndIf
; If (*pLong\l = 6357070 And CompareMemory(*c, @"+Infinity", 18)) Or (*pLong\l = 6357070 And CompareMemory(*c, @"Infinity", 16))
; ProcedureReturn Infinity()
; EndIf
; If *pLong\l = 6357070 And CompareMemory(*c, @"-Infinity", 18)
; ProcedureReturn -Infinity()
; EndIf
If *c\c = '-'
*c + #SzChar
negative = 1
ElseIf *c\c = '+'
*c + #SzChar
EndIf
While *c\c = '0'
*c + #SzChar
Wend
; get the integer part
If *c\c > 47 And *c\c < 58 ; to avoid multiplying by 10 and then dividing by 10 unnecessarily.
result + *c\c - 48
*c + #SzChar
While *c\c > 47 And *c\c < 58
; pos + 1
result * 10 + *c\c - 48
*c + #SzChar
Wend
; If pos > 14
; ProcedureReturn NaN()
; EndIf
EndIf
; get the decimal part of a number
If *c\c = '.'
*c + #SzChar
While *c\c > 47 And *c\c < 58
; pos + 1
divider * 10
decimal * 10 + *c\c - 48
*c + #SzChar
Wend
; If pos > 14
; ProcedureReturn NaN()
; EndIf
result + decimal / divider
EndIf
; get an exponent
If *c\c = 'e' Or *c\c = 'E'
*c + #SzChar
If *c\c = '-'
*c + #SzChar
negative2 = 1
EndIf
While *c\c = '0'
*c + #SzChar
Wend
If *c\c > 47 And *c\c < 58 ; to avoid multiplying by 10 and then dividing by 10 unnecessarily.
exponent + *c\c - 48
*c + #SzChar
While *c\c > 47 And *c\c < 58
exponent * 10 + *c\c - 48
*c + #SzChar
Wend
If negative2
result / Pow2(10, exponent)
Else
result * Pow2(10, exponent)
EndIf
EndIf
EndIf
If negative
result = -result
EndIf
ProcedureReturn result
EndProcedure
; Debug ValD2(@"922337203685477") ; max
; Debug ValD2(@"92233720368547.3") ; max (decimal)
; Debug ValD2(0) ; pointer 0
; Debug ValD2(@"") ; empty line
; Debug ValD2(@"NaN") ; special value
; Debug ValD2(@"Infinity")
; Debug ValD2(@"+Infinity")
; Debug ValD2(@"-Infinity")
; Debug ValD2(@"1.2.3") ; Two dots
; Debug ValD2(@"00123") ; Preceding zeros
; Debug ValD2(@"-12 3") ; a negative number
; Debug ValD2(@"567.123") ; a number with a decimal part
; Debug ValD2(@"000123.00456")
; Debug ValD2(@".789") ; a number without a preceding zero
; Debug ValD2(@"789.")
; Debug ValD2(@"-2.923e01") ; exponential notation
; Debug ValD2(@"-2.923E01")
; Debug ValD2(@"300e05")
; Debug ValD2(@"300e-02")
#Counts = 1000000
Define Time, String.s, Double.d, i
Time = ElapsedMilliseconds()
String = "567.123"
For i = 1 To #Counts
Double = ValD2(@String)
Next
Time = ElapsedMilliseconds()-Time
OpenConsole()
PrintN("Single call time: "+StrD(1000.0*Time/#Counts)+" µs")
Input()
Code: Select all
; single digit quicky?
*scTest = *pString + 2
If *scTest\c = 0
If *pString\c > 47 And *pString\c < 58
ProcedureReturn *pString\c - '0'
Else
ProcedureReturn 0.0
EndIf
EndIf
Without creating a variable:
Code: Select all
; single digit quicky?
If PeekC(*c + #SzChar) = 0
If *c\c > 47 And *c\c < 58
ProcedureReturn *c\c - 48
Else
ProcedureReturn 0.0
EndIf
EndIf
Code: Select all
While *pString\c <> endChar
Last edited by AZJIO on Sat Oct 04, 2025 2:56 pm, edited 1 time in total.
Re: Why are ValF & ValD so slow?
Code: Select all
This code is dangerous...
This wasn't a 'Tricks 'n' Tips' post...
Re: Why are ValF & ValD so slow?
It's very interesting to me how PB has to struggle between low and high-level needs (but generally there are many experienced programmers here who can propose faster "low-level" alternatives in no time…)
I stop here because my duty is to criticize you

Re: Why are ValF & ValD so slow?
You have a bug in the use of your Pow2() function.AZJIO wrote: Fri Oct 03, 2025 1:35 amCode: Select all
Procedure Pow2(n, replay) Protected i, result = 1 While replay > 0 replay - 1 result * n Wend ProcedureReturn result EndProcedure
A double number can have exponents up to e+308 oder e-308, but the variable result and the return type is just an integer, it must be a double.
Further, for exponents like e300 your loop iterates over 300 times.
It would be more efficient to use the Exponentiation by squaring method.
Code: Select all
Procedure.d Pow2(n, replay)
Protected result.d = 1, bit = 1<<8 ; most significant bit, 256, enough for double exponent
If replay > 308
ProcedureReturn Infinity()
EndIf
While replay & bit = 0 And bit ; Searching the most significant bit
bit >> 1
Wend
While bit > 0
result * result
If replay & bit
result * n
EndIf
bit >> 1
Wend
ProcedureReturn result
EndProcedure
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and more ― Typeface - Sprite-based font include/module
Lizard - Script language for symbolic calculations and more ― Typeface - Sprite-based font include/module
Re: Why are ValF & ValD so slow?
Should be much faster in 6.30b3
Re: Why are ValF & ValD so slow?
Both ValF & ValD are much quicker for me now Fred, thanks a lot.

Re: Why are ValF & ValD so slow?
Glad to hear! 
