Post by (X) on Feb 9, 2023 15:05:50 GMT 1
I thought of producing a function: F_Annotation_Int_Str() that annotates a Big Int string with metric symbols to break-up a long sequence:
"765432198765432198765432211111111"
into a more intuitive format:
"765Q_432R_198Y_765Z_432E_198P_765T_432G_211M_111k_111"
Function F_Annotated_Int_Str(n$) As String
'#################################################################################
'
' DISCLAIMER: THIS CODE IS OFFERED AS IS FOR EDUCATIONAL PURPOSES.
' YOU ARE FREE TO USE, COPY AND DISTRIBUTE.
' THE USE OF THIS CODE IS AT YOUR OWN RISK.
' I ACCEPT NO LIABILITY NOR MAKE ANY CLAIM OF
' CORRECTNESS OR SUITABILITY IN PART OR IN WHOLE.
'
'#################################################################################
'
' AUTHOR (X)
' EMAIL xman.gb32@gmail.com
' WEBSITE https://gfabasic32.blogspot.com/
' FORUM https://gb32.proboards.com/
' STARTED 2023-02-07
' UPDATED <ISO date>
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' One can easily add this function to a library and the following line would
' export the function to the main program. See GFA Help for $Library creation.
'
//$Export Func F_Annotated_Int_Str "(<Int_Str$>) as String"
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Annotate the number string with metric inspired symbols to break up the string
' into easily identifiable multiples of 1000.
'
Local Annotated_n$ // Annotated number string
Local SubStr_n$ // Sub-string of the number string: n$
Local Int cSubStr_Cnt = 3
Local Int cNumStr_Len = Len(n$)
Local Int iSubStr_Start = cNumStr_Len
'Trace cNumStr_Len
Local Int iDigit = 0 // iDigit stores the index of the digits from right to left.
If (cNumStr_Len => 4)
Do
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Set the index of the digit in increments of the sub-string count or grouping
' which is intended to be 3 to subdivide the number by the thousands.
'
iDigit += cSubStr_Cnt
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Based on the digit index and the length of the number string, set the start
' index of sub-string operation, which will tell the SubStr() function where
' to start capturing the specified count of characters from the specified string.
'
iSubStr_Start = cNumStr_Len - iDigit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' If iSubStr_Start has overrun the to the left, then, perform one final arrangement
' of the cSubStr_Cnt and iSubStr_Start variable values.
'
If (iSubStr_Start < 1)
cSubStr_Cnt = iSubStr_Start + cSubStr_Cnt
iSubStr_Start = 1
EndIf
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Select a sub-string of the number string: n$, using the specified start and
' count variables: iSubStr_Start and cSubStr_Cnt.
'
SubStr_n$ = SubStr(n$, iSubStr_Start, cSubStr_Cnt)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Build the annotated number string based on the digit index.
' The F_annotation() function returns a metric symbol: {k,M, G .. Q .. QQ}
' to make it easier to identify and grasp the amplitude of the number.
' To me this is much better than a long unbroken sequence of digits.
'
Annotated_n$ = SubStr_n$ & F_Annotation(iDigit) & Annotated_n$
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Once the sub-string start index has been set to 1, we are done.
'
Loop Until (iSubStr_Start = 1)
Else // Not (cNumStr_Len => 4)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' There is no need to annotate a number of 3 or less digits.
'
Annotated_n$ = n$
EndIf
Return Annotated_n$
EndFunc
Function F_Annotation(i As Int) As String
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' To breakup a long sequence of numbers into multiples of 1000 we can use the
' ISO or metric conventions of symbols: {k, M, G, T .. Q .. QQ}
' I added an underscore to make it even easier to pick out the groupings.
' For example:
'
' 765Q_432R_198Y_765Z_432E_198P_765T_432G_211M_111k_111
'
Local Annotation$
Select i
Case > 63
Annotation$ = ","
Case 63
Annotation$ = "QQ_"
Case 60
Annotation$ = "RQ_"
Case 57
Annotation$ = "YQ_"
Case 54
Annotation$ = "ZQ_"
Case 51
Annotation$ = "EQ_"
Case 48
Annotation$ = "PQ_"
Case 45
Annotation$ = "TQ_"
Case 42
Annotation$ = "GQ_"
Case 39
Annotation$ = "MQ_"
Case 36
Annotation$ = "kQ_"
Case 33
Annotation$ = "Q_"
Case 30
Annotation$ = "R_"
Case 27
Annotation$ = "Y_"
Case 24
Annotation$ = "Z_"
Case 21
Annotation$ = "E_"
Case 18
Annotation$ = "P_"
Case 15
Annotation$ = "T_"
Case 12
Annotation$ = "G_"
Case 9
Annotation$ = "M_"
Case 6
Annotation$ = "k_"
Case 3
Annotation$ = "" /* "."
EndSelect
Return Annotation$
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' From: https://en.wikipedia.org/wiki/Metric_prefix
'
' quetta Q 10^30 1000000000000000000000000000000 2022
' ronna R 10^27 1000000000000000000000000000 2022
' yotta Y 10^24 1000000000000000000000000 1991
' zetta Z 10^21 1000000000000000000000 1991
' exa E 10^18 1000000000000000000 1975
' peta P 10^15 1000000000000000 1975
' tera T 10^12 1000000000000 1960
' giga G 10^9 1000000000 1960
' mega M 10^6 1000000 1873
' kilo k 10^3 1000 1795
' hecto h 10^2 100 1795
' deca da 10^1 10 1795
'
EndFunc