Just thought I should try and make things a little clearer, and correct another minor flaw I'd found in the Format Float routine (I promise, I'll check my code a lot better in future!). I'd found that the DBC Val() function broke down at certain numbers, so I created these based on some pseudocode Latch gave me.
String to Int function - for DBC integers and the DBPro "Integer" data type.
This includes a validation check, returning 0 if any non-digit characters are found, rounding off decimal places (5 is rounded up automatically) and returning +/-999999999 if the value of the input string exceeds this (since any larger numbers could exceed the assigned four bytes).
Rem * Title : String To Int
Rem * Author : Robert the Robot
Rem * Date : 24/2/08
rem *******************************************************
rem Converts A String To An Integer with a validation check
rem *******************************************************
Print str_to_int("198.2")
end
Function Str_To_Int(Input$)
rem Set up variables
New$ = ""
NewInteger = 0
RoundDecimalUp = 0
NegFlag = 0
rem If negative then set flag, and remove first character
If Mid$(Input$, 1) = "-"
NegFlag=1
Temp$ = Right$(Input$, Len(Input$)-1)
else
Temp$ = Input$
endif
rem Check string for non-number characters
StringLength = Len(Temp$)
For N = 1 to StringLength
If RoundDecimalUp = 0
TempNo = Asc(Mid$(Temp$, N))
If TempNo > 46 and TempNo <= 57 and TempNo<>47
New$ = New$ + Mid$(Temp$, N)
else
rem If a decimal point is found
If TempNo = 46
If Val(Mid$(Temp$, N+1))>=5
RoundDecimalUp = 1
else
rem Don't count any more characters
RoundDecimalUp = 0
N = StringLength+1
endif
else
ExitFunction 0
endif
endif
endif
Next N
rem If number is more than 9 letters, it's too big!
rem Return the max safe value instead: +/-999999999
If len(New$)>9
If NegFlag = 1
NewInteger = 0-999999999
else
NewInteger = 999999999
endif
ExitFunction NewInteger
endif
rem Set up variables
StringLength = Len(New$)
NewInteger = 0
Power = StringLength
For N = 1 to StringLength
rem Inc the final number, by a number raised to the power of (nchars -1)
Inc NewInteger,(ASC(Mid$(New$, N))-48)*(10^(Power-1))
Dec Power, 1
next N
rem Round up any decimals, and handle negative integers
If RoundDecimalUp = 1 then NewInteger = NewInteger +1
If NegFlag=1 then NewInteger = 0-NewInteger
EndFunction NewInteger
String to Float function - for DBC floats and the DBPro "Real" data type.
This includes a validation check, returning 0 if any non-digit characters are found or if more than one decimal place has been entered, and returning +/-999999999 if the value of the input string exceeds this (since any larger numbers could exceed the assigned four bytes).
Rem * Title : String To Float
Rem * Author : Robert the Robot
Rem * Date : 24/2/08
rem ****************************************************
rem Converts a String of Text to a Float with validation
rem ****************************************************
Print Str_To_Float("-1000000000.123456")
Print Str$(str_to_Float("-100.1"))
end
Function Str_To_Float(String$)
rem Set up variables
NewFloat# = 0
NegFlag = 0
NoDps = 0
Temp$ = ""
New$ = ""
Int$ = ""
rem If negative then set flag, and remove first character
If Mid$(String$, 1) = "-"
NegFlag=1
Temp$ = Right$(String$, Len(String$)-1)
else
Temp$ = String$
endif
rem Check string for non-number characters
StringLength = Len(Temp$)
For N = 1 to StringLength
TempNo = Asc(Mid$(Temp$, N))
If TempNo >= 46 and TempNo <= 57 and TempNo<>47
New$ = New$ + Mid$(Temp$, N)
If TempNo = 46 then NoDps = NoDps + 1
else
rem A non-number has been found so return zero
ExitFunction 0
endif
rem If more than one decimal point, return zero
If NoDps>1 then ExitFunction 0
Next N
rem Work out the integer part of the String
T = 1
While T<=Len(New$)
If Mid$(New$, T) = "."
Int$ = Left$(New$, T-1)
Exit
else
Inc T
endif
EndWhile
rem If no decimal point is found
If Int$ = ""
Int$ = New$
endif
rem If integer string is more than 9 letters, it's too big!
rem Return the max safe value instead: +/-999999999
If len(Int$)>9
If NegFlag = 1
NewFloat# = 0-999999999
else
NewFloat# = 999999999
endif
ExitFunction NewFloat#
endif
rem Set up variables
StringLength = Len(Int$)
NewFloat# = 0
Power = StringLength
rem Generate integer part of float
For N = 1 to StringLength
Inc NewFloat#,(ASC(Mid$(Int$, N))-48)*(10^(Power-1))
Dec Power, 1
next N
rem Set up variables again
Power# = 0.1
rem generate float part
For N = Len(Int$)+2 to Len(New$)
Inc NewFloat#,(ASC(Mid$(New$, N))-48)*(Power#)
Power# = Power#/10
next N
If NegFlag=1 then NewFloat# = 0-NewFloat#
EndFunction NewFloat#
String to DoubleInt function - for DBPro "Double Integer" data type ONLY!
This function has not been tested, since I do not own DBPro and so cannot compile it. I was trying to get it working for Calcyman (see later posts), but I believe this will now work. The problem was that I as trying to construct an 8-byte integer using a 4-byte variable - result, misery. The New line of code at the start of the function "NewInteger as DOUBLE INTEGER" should take care of this. Please post if you have any problems.
The function includes a validation check, returning 0 if any non-digit characters are found, rounding off decimal places (5 is rounded up automatically) and returning +/-999999999999999999 if the value of the input string exceeds this (since any larger numbers could exceed the assigned eight bytes).
Rem * Title : String To Int
Rem * Author : Robert the Robot
Rem * Date : 6/4/08
rem *************************************************************
rem Converts A String To A Double Integer with a validation check
rem *************************************************************
Print str_to_DoubleInt("192.768")
end
Function Str_To_DoubleInt(Input$)
rem Set up variables
New$ = ""
NewInteger as DOUBLE INTEGER
NewInteger = 0
RoundDecimalUp = 0
NegFlag = 0
rem If negative then set flag, and remove first character
If Mid$(Input$, 1) = "-"
NegFlag=1
Temp$ = Right$(Input$, Len(Input$)-1)
else
Temp$ = Input$
endif
rem Check string for non-number characters
StringLength = Len(Temp$)
For N = 1 to StringLength
If RoundDecimalUp = 0
TempNo = Asc(Mid$(Temp$, N))
If TempNo > 46 and TempNo <= 57 and TempNo<>47
New$ = New$ + Mid$(Temp$, N)
else
rem If a decimal point is found
If TempNo = 46
If Val(Mid$(Temp$, N+1))>=5
RoundDecimalUp = 1
else
rem Don't count any more characters
RoundDecimalUp = 0
N = StringLength+1
endif
else
ExitFunction 0
endif
endif
endif
Next N
rem If number is more than 18 letters, it's too big!
rem Return the max safe value instead: +/-999999999
If len(New$)>18
If NegFlag = 1
NewInteger = 0-999999999999999999
else
NewInteger = 999999999999999999
endif
ExitFunction NewInteger
endif
rem Set up variables
StringLength = Len(New$)
NewInteger = 0
Power = StringLength
For N = 1 to StringLength
rem Inc the final number, by a number raised to the power of (nchars -1)
Inc NewInteger,(ASC(Mid$(New$, N))-48)*(10^(Power-1))
Dec Power, 1
next N
rem Round up any decimals, and handle negative integers
If RoundDecimalUp = 1 then NewInteger = NewInteger +1
If NegFlag=1 then NewInteger = 0-NewInteger
EndFunction NewInteger
String to DoubleFloat function - for DBPro "Double Float" data type ONLY!
as with the above function, this has not been tested. However, the new line of code at the start of the function "NewFloat as DOUBLE FLOAT" should take care of this. Please post if you have any problems.
The function includes a validation check, returning 0 if any non-digit characters are found, rounding off decimal places (5 is rounded up automatically) and returning +/-999999999999999999 if the value of the input string exceeds this (since any larger numbers could exceed the assigned eight bytes).
Rem * Title : String To Float
Rem * Author : Robert the Robot
Rem * Date : 24/2/08
rem **********************************************************
rem Converts a String of Text to a DoubleFloat with validation
rem **********************************************************
Print Str_To_Float("-1000000000.123456")
Print Str$(str_to_Float("-100.1"))
end
Function Str_To_Float(String$)
rem Set up variables
NewFloat# as DOUBLE FLOAT
NewFloat# = 0.0
NegFlag = 0
NoDps = 0
Temp$ = ""
New$ = ""
Int$ = ""
rem If negative then set flag, and remove first character
If Mid$(String$, 1) = "-"
NegFlag=1
Temp$ = Right$(String$, Len(String$)-1)
else
Temp$ = String$
endif
rem Check string for non-number characters
StringLength = Len(Temp$)
For N = 1 to StringLength
TempNo = Asc(Mid$(Temp$, N))
If TempNo >= 46 and TempNo <= 57 and TempNo<>47
New$ = New$ + Mid$(Temp$, N)
If TempNo = 46 then NoDps = NoDps + 1
else
rem A non-number has been found so return zero
ExitFunction 0
endif
rem If more than one decimal point, return zero
If NoDps>1 then ExitFunction 0
Next N
rem Work out the integer part of the String
T = 1
While T<=Len(New$)
If Mid$(New$, T) = "."
Int$ = Left$(New$, T-1)
Exit
else
Inc T
endif
EndWhile
rem If no decimal point is found
If Int$ = ""
Int$ = New$
endif
rem If integer string is more than 18 letters, it's too big!
rem Return the max safe value instead: +/-999999999
If len(Int$)>18
If NegFlag = 1
NewFloat# = 0-999999999999999999
else
NewFloat# = 999999999999999999
endif
ExitFunction NewFloat#
endif
rem Set up variables
StringLength = Len(Int$)
NewFloat# = 0
Power = StringLength
rem Generate integer part of float
For N = 1 to StringLength
Inc NewFloat#,(ASC(Mid$(Int$, N))-48)*(10^(Power-1))
Dec Power, 1
next N
rem Set up variables again
Power# = 0.1
rem generate float part
For N = Len(Int$)+2 to Len(New$)
Inc NewFloat#,(ASC(Mid$(New$, N))-48)*(Power#)
Power# = Power#/10
next N
If NegFlag=1 then NewFloat# = 0-NewFloat#
EndFunction NewFloat#
I was envious of DBPro's Str$() command, with the option to format the returned string to a set number of decimal places. I therefore created this (now updated to remove a couple of minor rounding bugs when the decimals hit something like 0.09999). This is for DBC only, as DBPRo has already got it:
If an exponential is found, the algorithm can follow one of four modes
1 = return exponential string
2 = remove exponential, return a pure decimal string
3 = remove exponential, return a decimal formatted to dp
4 = return exponential, decimal string formatted to keep a 12 digit string (13 digits if a minus sign is present)
If no exponential is found, the number is rounded like an ordinary float, and riounded to the specified number of decimal places.
Rem * Title : Format Float
Rem * Author : Robert the Robot
Rem * Date : 24/2/08
rem *******************************************
rem Format Floats to a number of decimal places
rem *******************************************
rem Sample program - see below for details on how to use the function
Input# = 1.01
sync on
Do
If Leftkey() = 1 then Input# = Input#+0.01
If Rightkey() = 1 then Input# = Input#-0.01
Print Input#
Print FormatFloat(Input#, 2, 4) + " Max 12digit string"
Print FormatFloat(Input#, 2, 3) + " Remove exponential, return value formatted to dp"
Print FormatFloat(Input#, 2, 2) + " Add zeros as needed to remove exponential"
Print FormatFloat(Input#, 2, 1) + " Effectively just the Str$() function"
Sync : Cls
Loop
end
rem This takes any float and converts it to a string with up to 6 decimal places.
rem Fives are rounded up automatically
remstart
Parameters:
Input# = the float you wish to format
dp = number of decimal places (cannot exceed 6 as DBC rounds all floats to 6 sig figs)
E: If an exponential is found, the algorithm can follow one of four modes
1 = return exponential string
2 = remove exponential, return a pure decimal string
3 = remove exponential, return a decimal formatted to dp
4 = return exponential, decimal string formatted to keep a 12 digit string
If no exponential is found, the number is roundeed like an oridnary float
remend
Function FormatFloat(Input#, dp, E)
rem Limits for decimal points range
If dp>6 then dp = 6
If dp<=0 then dp = 1
Input$ = Str$(Input#)
Output$ = ""
Integer$ = ""
Decimal$ = ""
Temp$ = ""
Sign$ = ""
rem Store the sign
If Left$(Input$, 1) = "-"
Sign$ = "-"
Input$ = Right$(Input$, Len(Input$)-1)
endif
rem Check for an exponential
If Left$(Right$(Input$, 5), 1) = "e"
If E = 1 then ExitFunction (Sign$+Input$)
If E = 2 or E = 3
T = 1
Repeat
If Mid$(Input$, T) = "."
rem Store exponent, remove decimal point, remove exponent from output
Exponent$ = Right$(Input$, 5)
Output$ = Left$(Input$, T-1) + Right$(Input$, Len(Input$)-T)
Output$ = Left$(Output$, Len(Output$)-5)
Exit
else
Inc T
endif
Until T>=Len(Input$)
rem If no decimal place found...
If Output$ = ""
Output$ = Left$(Input$, Len(Input$)-5)
Exponent$ = Right$(Input$, 5)
endif
If Left$(Right$(Exponent$, 4), 1) = "-"
rem Add decimal places
Temp$ = "0."
For T = 1 to Val(Right$(Exponent$, 3))-1
Temp$ = Temp$ + "0"
Next T
Output$ = Temp$ + Output$
else
rem Add zeros on to the end
a = Len(Output$)-1
For T = 1 to (Val(Right$(Exponent$, 3))-a)
Output$ = Output$ + "0"
Next T
endif
If E = 2 then ExitFunction (Sign$+Output$)
endif
If E = 4
rem Assign the number and the exponent
Output$ = Left$(Input$, Len(Input$)-5)
Exponent$ = Right$(Input$, 5)
rem If there is no decimal, add a decimal point
If (Len(Output$) = 1) then Output$ = Output$ + "."
a = Len(Output$)-2 : dp = 5
For T = 1 to (dp-a)
Output$ = Output$+"0"
Next T
Output$ = Sign$ + Output$ + Exponent$
ExitFunction Output$
endif
endif
rem Split string to integer and decimal
If Output$ = "" then Output$ = Input$
T = 1
Repeat
If Mid$(Output$, T) = "."
Integer$ = Left$(Output$, T-1)
Decimal$ = Right$(Output$, Len(Output$)-Len(Integer$)-1)
Exit
else
Inc T
endif
Until T >= Len(Output$)
rem If no decimal place
If Integer$ = ""
Integer$ = Output$
Decimal$ = "0"
endif
a = Len(Decimal$)
If a>=dp
rem Only keep last decimal place
Decimal$ = Left$(Decimal$, (dp+1))
else
rem Not enough decimal places - add a few 0s and exit
For T = 1 to (dp-a)
Decimal$ = Decimal$ + "0"
Next T
Output$ = Integer$ + "." + Decimal$
ExitFunction (Sign$+Output$)
endif
rem Add an extra dp for rounding purposes
If a = dp then Decimal$ = Decimal$ + "0"
rem The actual rounding
Repeat
If Val(Right$(Decimal$, 1))>= 5
Decimal$ = Left$(Decimal$, Len(Decimal$)-1)
If Right$(Decimal$, 1) = "9"
rem Clearing 9's
Repeat
Decimal$ = Left$(Decimal$, Len(Decimal$)-1)
Until (Decimal$ = "") or (Right$(Decimal$, 1) <> "9")
If Decimal$ = ""
rem No dps so increase integer
Integer$ = Str$(Val(Integer$)+1)
else
rem dps so add 1 to last decimal place
Decimal$ = Left$(Decimal$, Len(Decimal$)-1) + Str$(Val(Right$(Decimal$, 1))+1)
endif
else
rem greater than 5, but not 9 - clear last character, and add 1 to Decimal
Decimal$ = Left$(Decimal$, Len(Decimal$)-1) + Str$(Val(Right$(Decimal$, 1))+1)
endif
else
rem Rounding digit less than 5 so do nothing
Decimal$ = Left$(Decimal$, Len(Decimal$)-1)
endif
Until Len(Decimal$)<=dp
rem Once again, add some decimal points if necessary
a = Len(Decimal$)
For T = 1 to (dp-a)
Decimal$ = Decimal$ + "0"
Next T
Output$ = Sign$ + Integer$ + "." + Decimal$
EndFunction Output$
Hope these are of use, and sorry for all the bother.
It is said there are 10 types of people in this world - those who understand binary, and those who have friends!