Results 1 to 8 of 8

Thread: Order of Magnitude Rounding

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2000
    Location
    Sedgefield
    Posts
    337

    Order of Magnitude Rounding

    Is there a clever algorithm for rounding a number by order of magnitude?

    I'm trying to set the axis bounds on a chart control such that if, for example,

    max Y = 5637, max axis Y = 6000
    min Y = 2312, min axis Y = 2000

    I'd guess I'd also want to round up and down to the largest order of magnitude. Thus:

    max Y = 5637, max axis Y = 6000
    min Y = 134, min axis Y = 0 (i.e. not 100).

    Dan

    Outside of a dog, a book is a man's best friend.
    Inside of a dog, it's too dark to read.

  2. #2
    Super Moderator si_the_geek's Avatar
    Join Date
    Jul 2002
    Location
    Bristol, UK
    Posts
    41,974
    How's this?
    VB Code:
    1. max_len = 10^(len(maxY)-1)
    2. max_axisY = -int(-maxy/max_len) * max_len   ' using Int with -ve to round up!
    3. min_axisY = int(miny/max_len) * max_len

  3. #3
    vbuggy krtxmrtz's Avatar
    Join Date
    May 2002
    Location
    In a probability cloud
    Posts
    5,573
    Here's a subroutine I have used with success (probably it will have to be somewhat modified to suit your needs). I'm not sure it works quite "foolproof",I think there's an error with negative numbers...
    I am attaching a demo project.

    Btw the variables' names are not too explicit as to their meaning, as I'm using an old (with a limited number of characters per variable name) Fortran routine that I converted almost literally.

    VB Code:
    1. Public Sub RoundToNearest(zs)
    2. 'Given a number zs (of single type), another number is calculated
    3. 'of similar order of magnitude but "rounded up to the nearest number
    4. 'of a series a(i) or one of their multiples or submultiples
    5. 'The numbers a(1), a(2), ... are up to the user's taste
    6. 'I have chosen 1, 2 and 5, so that my rounded number
    7. 'will be one in the series 1, 2, 5, 10, 20, 50, 100, 200, 500, ...
    8. 'or 0.1, 0.2, 0.5, 0.01, 0.02, 0.05, ...
    9.  
    10. 'The result is placed in zs so the original is destroyed
    11. '(i.e. work with a copy)
    12.  
    13.     Dim a(1 To 3) as integer
    14.     Dim zs as single
    15.  
    16.     a(1) = 1: a(2) = 2: a(3) = 5
    17.  
    18.     For i = 1 To 3
    19.         If zs = a(i) Then Exit Sub
    20.     Next
    21.     jsign = Sgn(zs - 1)
    22.     lex = (jsign - 1) \ 2
    23.     f = 10 ^ lex
    24. Start:
    25.     For k = 1 To 3
    26.         kk = k + 1
    27.         ff = f
    28.         If k = 3 Then
    29.             kk = 1
    30.             ff = 10 * ff
    31.         End If
    32.         a1 = a(k) * f
    33.         a2 = a(kk) * ff
    34.         If zs < a1 Or zs > a2 Then GoTo Endloop
    35.         If zs = a1 Or zs = a2 Then Exit Sub
    36.         d1 = Abs(zs - a1)
    37.         d2 = Abs(zs - a2)
    38.         zs = a2
    39.         If d1 < d2 Then zs = a1
    40.         Exit Sub
    41. Endloop:
    42.     Next
    43.     f = f * 10 ^ jsign
    44.     GoTo Start
    45. End Sub
    Attached Files Attached Files
    Last edited by krtxmrtz; Dec 2nd, 2002 at 08:56 AM.

  4. #4

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2000
    Location
    Sedgefield
    Posts
    337

    Question Idea

    The simplest and most flexible method?

    Format numbers in scientific notation:

    Code:
    4678 = 4.678x10³
    Round up (or down) the mantissa?

    The trick would be acquiring the mantisssa?

    We can get the exponent from

    Code:
    Int(log10(4678)) ~ Int(3.67) = 3

    Dan

    Outside of a dog, a book is a man's best friend.
    Inside of a dog, it's too dark to read.

  5. #5

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2000
    Location
    Sedgefield
    Posts
    337

    Something like this....

    VB Code:
    1. Option Explicit
    2.  
    3. Private Sub Command1_Click()
    4.     Dim dTest As Double
    5.     Dim dExp As Double
    6.     Dim dOrder As Double
    7.     Dim dMantissa As Double
    8.     Dim dRoundedUp As Double
    9.     Dim dRoundedDown As Double
    10.    
    11.     dTest = 4678#
    12.     dExp = Int(Log10(dTest))
    13.     dOrder = 10 ^ dExp
    14.    
    15.     dMantissa = dTest / dOrder
    16.    
    17.     dRoundedUp = Ceil(dMantissa) * dOrder
    18.     dRoundedDown = Floor(dMantissa) * dOrder
    19. End Sub
    20.  
    21. Static Function Log10(x As Double) As Double
    22.    Log10 = Log(x) / Log(10#)
    23. End Function
    24.  
    25. Function Ceil(x As Double) As Double
    26.     If Round(x) = x Then
    27.         Ceil = x
    28.     Else
    29.         Ceil = Round(x + 0.5)
    30.     End If
    31. End Function
    32.  
    33. Function Floor(x As Double) As Double
    34.     If Round(x) = x Then
    35.         Floor = x
    36.     Else
    37.         Floor = Round(x - 0.5)
    38.     End If
    39. End Function

    Dan

    Outside of a dog, a book is a man's best friend.
    Inside of a dog, it's too dark to read.

  6. #6

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2000
    Location
    Sedgefield
    Posts
    337

    Giving rise to...

    VB Code:
    1. Private Sub Command1_Click()
    2.     Dim dTest As Double
    3.     Dim dRoundedUp As Double
    4.     Dim dRoundedDown As Double
    5.     dTest = 0.001234
    6.     dRoundedUp = MagnitudeRound(dTest, True)
    7.     dRoundedDown = MagnitudeRound(dTest, False)
    8. End Sub
    9.  
    10. Function MagnitudeRound(dNumber As Double, Optional bRoundUp As Boolean = True, Optional nOrder As Variant) As Double
    11.     Dim dOrder As Double
    12.     Dim dMantissa As Double
    13.    
    14.     If IsMissing(nOrder) Then
    15.         nOrder = Int(Log(dNumber) / Log(10#))
    16.     End If
    17.    
    18.     dOrder = 10 ^ nOrder
    19.    
    20.     dMantissa = dNumber / dOrder
    21.    
    22.     If (bRoundUp) Then
    23.         MagnitudeRound = Ceil(dMantissa) * dOrder
    24.     Else
    25.         MagnitudeRound = Floor(dMantissa) * dOrder
    26.     End If
    27.    
    28. End Function
    29.  
    30. Function Ceil(x As Double) As Double
    31.     If Round(x) = x Then
    32.         Ceil = x
    33.     Else
    34.         Ceil = Round(x + 0.5)
    35.     End If
    36. End Function
    37.  
    38. Function Floor(x As Double) As Double
    39.     If Round(x) = x Then
    40.         Floor = x
    41.     Else
    42.         Floor = Round(x - 0.5)
    43.     End If
    44. End Function

    Dan

    Outside of a dog, a book is a man's best friend.
    Inside of a dog, it's too dark to read.

  7. #7
    Super Moderator si_the_geek's Avatar
    Join Date
    Jul 2002
    Location
    Bristol, UK
    Posts
    41,974

    Re: Giving rise to...

    Originally posted by Judd
    VB Code:
    1. Private Sub Command1_Click()
    2.     Dim dTest As Double
    3.     Dim dRoundedUp As Double
    4.     Dim dRoundedDown As Double
    5.     dTest = 0.001234
    6.     dRoundedUp = MagnitudeRound(dTest, True)
    7.     dRoundedDown = MagnitudeRound(dTest, False)
    8. End Sub
    9.  
    10. Function MagnitudeRound(dNumber As Double, Optional bRoundUp As Boolean = True, Optional nOrder As Variant) As Double
    11.     Dim dOrder As Double
    12.     Dim dMantissa As Double
    13.    
    14.     If IsMissing(nOrder) Then
    15.         nOrder = Int(Log(dNumber) / Log(10#))
    16.     End If
    17.    
    18.     dOrder = 10 ^ nOrder
    19.    
    20.     dMantissa = dNumber / dOrder
    21.    
    22.     If (bRoundUp) Then
    23.         MagnitudeRound = Ceil(dMantissa) * dOrder
    24.     Else
    25.         MagnitudeRound = Floor(dMantissa) * dOrder
    26.     End If
    27.    
    28. End Function
    29.  
    30. Function Ceil(x As Double) As Double
    31.     If Round(x) = x Then
    32.         Ceil = x
    33.     Else
    34.         Ceil = Round(x + 0.5)
    35.     End If
    36. End Function
    37.  
    38. Function Floor(x As Double) As Double
    39.     If Round(x) = x Then
    40.         Floor = x
    41.     Else
    42.         Floor = Round(x - 0.5)
    43.     End If
    44. End Function
    Great code, but not relevant here.. the min value should round to the same order of magnitude of the max value
    max =5637 should round to 6000 - fine
    min = 134 should round to 0 - yours would round this to 100

    try this code in your command button:

    VB Code:
    1. Dim maxy As Long, miny As Long
    2. maxy = 5637
    3. miny = 134
    4.     dRoundedUp = MagnitudeRound(CDbl(maxy), True)
    5.     dRoundedDown = MagnitudeRound(CDbl(miny), False)
    6.  
    7. max_len = 10 ^ (Len(maxy) - 1)
    8. max_axisY = -Int(-maxy / max_len) * max_len
    9. min_axisY = Int(miny / max_len) * max_len
    10.  
    11. Msgbox "Max:   " & vbtab & dRoundedUp & vbtab & " or " & max_axisY  & vbcr _
    12.           & "Min:   " & vbtab & dRoundedDown & vbtab & " or " & min_axisY

  8. #8

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2000
    Location
    Sedgefield
    Posts
    337

    Talking

    That's why I included the order as an argument, you can specify the order to round to:

    Code:
    dTest = 123
    dRoundedUp = MagnitudeRound(dTest, True) = 200
    dRoundedDown = MagnitudeRound(dTest, False) = 100
    Code:
    dTest = 123
    dRoundedUp = MagnitudeRound(dTest, True, 1) = 130
    dRoundedDown = MagnitudeRound(dTest, False, 1) = 120
    Code:
    dTest = 123
    dRoundedUp = MagnitudeRound(dTest, True, 2) = 200
    dRoundedDown = MagnitudeRound(dTest, False, 2) = 100
    Code:
    dTest = 123
    dRoundedUp = MagnitudeRound(dTest, True, 3) = 1000
    dRoundedDown = MagnitudeRound(dTest, False, 3) = 0
    Makes the function more flexible

    Dan

    Outside of a dog, a book is a man's best friend.
    Inside of a dog, it's too dark to read.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width