This
was originally a one-line routine found on the newsgroups. However, the
original function failed to report the correct size of the integer
portion of a number when the number passed was a power of 10. With
the assistance of Rui Trigueiros the routine has been corrected to now accurately
return the number of digits in the integer portion of a number passed
to the function, up to a maximum of 10 ^ 16 -2. Thus if
9999.99999999 was passed, the function would return 4 representing the
number of digits before the decimal point.
The code also contains a test routine and a helper routine that will
return the decimal character used by the local system to separate the
integer portion of a number from the decimal side. This function is used
only by the test routine and is unneeded in the GetDigitCount function,
but can be used in any app to accurately return the current decimal
character. In fact, if you open control panel's regional settings
and change the decimal separator value you can see the effect of the
routine.
Revision history |
|
July 12.2004 |
Modified routine to correctly handle powers of 10
|
July 15.2004 |
Correction to handle rounding of numbers and variables with 0 value. |
|
Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Distribution: You can freely use this code in your own
' applications, but you may not reproduce
' or publish this code on any web site,
' online service, or distribute as source
' on any media without express permission.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Function GetDigitCount(inValue As Double) As Long
'due to the way doubles are represented,
'and incorrect value could be returned
'if inValue exceeds (10 ^ 16) - 2
'the next two lines are required in order
'to correctly handle all numbers up to
'(10 ^ 16) - 2. The routine will not work
'correctly in a compiled app if the INCREMENT
'constant code is placed in-line in the
'GetDigitCount line below.
Const INCREMENT As Double = 1 + (10 ^ -15)
inValue = Int(Abs(inValue))
If inValue > 0 Then
GetDigitCount = Int(Log(inValue + 0.99) / Log(10) + INCREMENT)
Else
GetDigitCount = 1
End If
End Function
Private Function GetLocalDecimalChar() As String
'helper routine for test code
'
'returns the char used as the decimal
'separator for the installed language per
'control panel>regional settings>customize
GetLocalDecimalChar = Mid$(CStr(3.3), 2, 1)
End Function
Private Sub Command1_Click()
'test code
Dim cnt As Long
Dim sNum As String
Dim sDigSep As String
Const MAXTEST As Long = 15
sDigSep = GetLocalDecimalChar()
'string with 1 to 15 9's - the decimal
'sign moves from left to right
For cnt = 1 To MAXTEST
sNum = String(cnt, "9") & _
IIf(cnt < MAXTEST, sDigSep & String(MAXTEST - cnt, "9"), "")
Print sNum, GetDigitCount(CDbl(sNum))
Next cnt
'simple tests for 0 and 1
Print
Print 0, , GetDigitCount(0)
Print 1, , GetDigitCount(1)
'results for powers of 10
For cnt = 1 To MAXTEST
sNum = "1" & String(cnt, "0")
Print sNum, GetDigitCount(CDbl(sNum))
Next cnt
End Sub |