Results 1 to 23 of 23

Thread: [RESOLVED] Odd Round behaviour

  1. #1

    Thread Starter
    Frenzied Member zaza's Avatar
    Join Date
    Apr 2001
    Location
    Borneo Rainforest Habits: Scratching
    Posts
    1,486

    Resolved [RESOLVED] Odd Round behaviour

    Something odd I've noticed in VBA.

    If you evaluate Round(16 * 1000/100,1) you will get 160.

    If you do Round(16 * 10000/1000,1) you will generate an overflow exception.

    If you put a tiny decimal in, though, you will be fine.

    Round(16.0001 * 10000/1000,1) = 160


    There must be some form of coercion to an integer form with a specific number of bytes if you don't use a decimal, which then trips the overflow.
    I use VB 6, VB.Net 2003 and Office 2010



    Code:
    Excel Graphing | Excel Timer | Excel Tips and Tricks | Add controls in Office | Data tables in Excel | Gaussian random number distribution (VB6/VBA,VB.Net) | Coordinates, Vectors and 3D volumes

  2. #2
    PowerPoster Spoo's Avatar
    Join Date
    Nov 2008
    Location
    Right Coast
    Posts
    2,656

    Re: Odd Round behaviour

    Zaza

    Interestingly, these also produce an overflow exception

    Code:
    Dim v2 As Long
    v2 = Round(CLng(16 * 10000) / 1000, 1)
    v2 = Round(CLng(16 * 10000 / 1000), 1)
    Spoo

  3. #3
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: Odd Round behaviour

    16.0001 must be "forcing" the calculation to use floating point - which loses precision before you would ever get an overflow error.

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  4. #4
    Frenzied Member
    Join Date
    Nov 2010
    Posts
    1,470

    Re: Odd Round behaviour

    you need to ensure that no part of the evaluation process exceeds any limits of the types currently in place during the expressions exaluation.

    multiplying by 100000 is enough to push you to said limit if you wrap the x/x portion in a pair of bracjets you will cause the multiplier to be reduced and aleaviate the problem!

    here to help

  5. #5
    PowerPoster Spoo's Avatar
    Join Date
    Nov 2008
    Location
    Right Coast
    Posts
    2,656

    Re: Odd Round behaviour

    Quote Originally Posted by incidentals View Post
    you need to ensure that no part of the evaluation process exceeds any limits of the types currently in place during the expressions exaluation.

    multiplying by 100000 is enough to push you to said limit if you wrap the x/x portion in a pair of bracjets you will cause the multiplier to be reduced and aleaviate the problem!

    here to help
    Isn't that what I did in post #2?
    How do you explain that the issue persists?

    Spoo

  6. #6
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: Odd Round behaviour

    Long in VBA must be really integer - limited to 32767 - right?

    That's like old mainframe basic's I used in the 80's.

    @spoo - how does this work?

    Code:
    Dim v2 As Long
    v2 = 32767
    v2 = v2 * 2
    Does it blow up on the multiplication line??

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  7. #7
    PowerPoster Spoo's Avatar
    Join Date
    Nov 2008
    Location
    Right Coast
    Posts
    2,656

    Re: Odd Round behaviour

    SZ

    Hmm.. per MSDN, for both VB6 and VBA ..

    CLng .. Long .. -2,147,438,648 to 2,147,843,647

    What am I missing?

    BTW .. I just tried your snippet in Excel
    Code:
    Dim v2 As Long
    v2 = 32767
    v2 = v2 * 2     ' << v2 = 65534
    It does not blow up on the multiplication line.

    Spoo

  8. #8
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: Odd Round behaviour

    Very odd - how about this

    Code:
    Dim v2 As Long
    v2 = Round(CLng(16 * 10000), 1)
    160,000 is not a very big number...

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  9. #9
    PowerPoster Spoo's Avatar
    Join Date
    Nov 2008
    Location
    Right Coast
    Posts
    2,656

    Re: Odd Round behaviour

    SZ

    These all fail with an "Overflow" error 6

    Code:
    Dim v2 As Long
    v2 = Round(CLng(16 * 10000), 1)
    v2 = Round(16 * 10000, 1)
    v2 = 16 * 10000
    .. but, these all work !
    Code:
    Dim v2 As Long
    v2 = 32767
    v2 = v2 * 2         ' v2 =      65,534
    v2 = v2 * 10000     ' v2 = 655,340,000
    Spoo
    Last edited by Spoo; Mar 10th, 2012 at 08:27 PM. Reason: get the commas right !!

  10. #10
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: Odd Round behaviour

    Tell me - does this fail?

    I believe it will work

    Code:
    Dim v2 As Long
    v2 = 0
    v2 = Round(v2 + (16 * 10000), 1)

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  11. #11

    Thread Starter
    Frenzied Member zaza's Avatar
    Join Date
    Apr 2001
    Location
    Borneo Rainforest Habits: Scratching
    Posts
    1,486

    Re: Odd Round behaviour

    No, that still breaks.

    Slightly worryingly, this also breaks with an overflow error:

    HTML Code:
    Public Sub test()
    
        Dim x As Long
        x = 1600 * 21
        
    End Sub
    although multiplying by 20.9999999 or 21.0000001 does not, both returning 33600.
    I use VB 6, VB.Net 2003 and Office 2010



    Code:
    Excel Graphing | Excel Timer | Excel Tips and Tricks | Add controls in Office | Data tables in Excel | Gaussian random number distribution (VB6/VBA,VB.Net) | Coordinates, Vectors and 3D volumes

  12. #12
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: Odd Round behaviour

    Using something like 20.999999 is forcing floating point - that is obvious.

    What is not so clear is why it's using WORD vs LONGWORD internally for math!!

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  13. #13

    Thread Starter
    Frenzied Member zaza's Avatar
    Join Date
    Apr 2001
    Location
    Borneo Rainforest Habits: Scratching
    Posts
    1,486

    Re: Odd Round behaviour

    Right, I think I understand what's going on here but not why.

    The following will break:
    Code:
    Public Sub test()
        Dim x As Long
        x = 1
        Debug.Print 32767 + 1
    End Sub
    but this will not:

    Code:
    Public Sub test()
        Dim x As Long
        x = 1
        Debug.Print 32767 + x
    End Sub

    This will break:

    Code:
    Public Sub test()
        Dim x As Long
        x = 1    
        Debug.Print 32767 + 1 + x   
    End Sub
    but this will not:

    Code:
    Public Sub test()
        Dim x As Long
        x = 1   
        Debug.Print 32767 + x + 1
    End Sub

    Clearly there is a bug in the internal calculation process which assigns all results of number-to-number integer calculations to a 16bit integer data type, but which is circumvented when evaluating variables of a different datatype.
    And in the last example even operator order is enough to make the difference.

    Also interestingly, this fails:

    Code:
    Public Sub test()
        Dim x As Integer
        Dim y As Long
        x = 1    
        y = 32767 + x + 1   
    End Sub
    So even though y is technically capable of storing the result, it cannot do so because setting x to Integer allows the result of the calculation to be coerced as an Integer again.
    CLng does not do anything here, and nor does bracketing.

    This seems pretty dodgy to me. Not only does the internal calculation model have a pretty serious limitation, but it also means that the implicit type conversion of VBA6 no longer works under VBA7 (which in some cases is no bad thing) and neither does a direct type conversion attempt.

    From doing a bit of poking around, it seems there have been a few changes in this area in the VBA7 upgrade, with the introduction of LongLong etc.

    I am using 32bit Office 2010 on 64bit Windows 7 Ultimate, so in principle I would think that operations like this should be fine.


    Must be a bug. Where do these things get reported? And does anybody listen?
    Last edited by zaza; Mar 11th, 2012 at 08:34 AM.
    I use VB 6, VB.Net 2003 and Office 2010



    Code:
    Excel Graphing | Excel Timer | Excel Tips and Tricks | Add controls in Office | Data tables in Excel | Gaussian random number distribution (VB6/VBA,VB.Net) | Coordinates, Vectors and 3D volumes

  14. #14

    Thread Starter
    Frenzied Member zaza's Avatar
    Join Date
    Apr 2001
    Location
    Borneo Rainforest Habits: Scratching
    Posts
    1,486

    Re: Odd Round behaviour

    Also, MSDN claims here that integer data types really no longer exist and that they are all Long behind the scenes, irrespective of how they are declared.
    Maybe they meant that they are converting everything to Integer behind the scenes instead!
    I use VB 6, VB.Net 2003 and Office 2010



    Code:
    Excel Graphing | Excel Timer | Excel Tips and Tricks | Add controls in Office | Data tables in Excel | Gaussian random number distribution (VB6/VBA,VB.Net) | Coordinates, Vectors and 3D volumes

  15. #15
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,687

    Re: Odd Round behaviour

    it's the 16 * 10000 calculation, it exceeds the integer limit of 32676. It's only a 16-bit number. so the moment it does that, it blows the limits of integer and errors out. It isn't the dim statement at all. That's why szlamany's code fails, but zaza's coerces the numbers into decimal, which is capable of the larger numbers, even if inaccurately. When dealing with mathmatical computations VB looks at the two numbers, decides which is the larger type, and coerces the types to the same larger type and returns that. Because 16 and 10000 are both coercable to integers, that's what it returns.

    if you were to clng the 16 AND the 10000, then you shouldn't get the overflow. Or if you dim two longs and set them to 16 & 10000 it should work, or even one long and set it to 16 or 10000, it should be fine.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  16. #16

    Thread Starter
    Frenzied Member zaza's Avatar
    Join Date
    Apr 2001
    Location
    Borneo Rainforest Habits: Scratching
    Posts
    1,486

    Re: Odd Round behaviour

    Indeed, it is definitely the actual calculation rather than the dimensioning of the variable. What seems odd to me is that this code:

    Code:
    Public Sub test()
        Dim x As Integer
        Dim y As Long
        x = 1    
        y = 32767 + x + 1   
    End Sub
    will cause an error, even though I have specified that the result of the addition is a Long data type.

    You are correct, tg, that using CLng(32767) + x + 1 does work, because the math operation now recognises that it needs to deal with a Long data type internally.

    However, I have never before seen this behaviour. Isn't there normally an implicit type conversion in internal math functions to allow you to add 1 to 32767 without either having to specify that one or both components of the calculation need to be treated as Long?
    I use VB 6, VB.Net 2003 and Office 2010



    Code:
    Excel Graphing | Excel Timer | Excel Tips and Tricks | Add controls in Office | Data tables in Excel | Gaussian random number distribution (VB6/VBA,VB.Net) | Coordinates, Vectors and 3D volumes

  17. #17
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,687

    Re: Odd Round behaviour

    it looks for the smallest, largest container it needs to hold hte numbers... otherwise it would have to wait until AFTER the calculation to determine what it should be... but then where would it put the result? that's why it scans the line to see what the numbers are, then allocates a memory address capable of holding the numbers, then does the calculation. since it sees two integers, it assumes, more often right than incorrectly, that the results will also be an integer and allocates an integer space in the memory.

    It has to do with how things are handled on the stack so that the operations can be handled.

    Now.... try this, see what happens (I don't have the ability to check it)... If I remember right... I *think* this will work...
    Code:
    Public Sub test()
        Dim x As Long
        Dim y As Long
        x = 1    
        y = x + 32767 + 1   
    End Sub
    I maybe wrong, but it seems to me that I remember reading somewhere that when there's no order of operation, that it uses the type of the left most item... since X is now dimmed as Long, it will treat the rest as a long... I think... but I don't remember if that applied only to multplication and division or all math operations.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  18. #18

    Thread Starter
    Frenzied Member zaza's Avatar
    Join Date
    Apr 2001
    Location
    Borneo Rainforest Habits: Scratching
    Posts
    1,486

    Re: Odd Round behaviour

    It works if there's anything in the operation that is classed as Long. Doesn't matter where it is.

    I don't have an older version of Office on this PC but I'm almost certain that this has changed; that historically VBA will automatically increase the required memory allocation and change the datatype accordingly unless you specifically attempt to allocate to a variable that has already been dimensioned to a smaller size.

    It definitely doesn't work like this in VB.Net, for example. Admittedly that's compiled, but you can compile a VBA project too.
    I use VB 6, VB.Net 2003 and Office 2010



    Code:
    Excel Graphing | Excel Timer | Excel Tips and Tricks | Add controls in Office | Data tables in Excel | Gaussian random number distribution (VB6/VBA,VB.Net) | Coordinates, Vectors and 3D volumes

  19. #19
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: Odd Round behaviour

    Quote Originally Posted by szlamany View Post
    Tell me - does this fail?

    I believe it will work

    Code:
    Dim v2 As Long
    v2 = 0
    v2 = Round(v2 + (16 * 10000), 1)
    Then why didn't this work for you?

    T-SQL I believe is left-to-right in regard to pre-evaluation of a formula to determine data typing.

    That MS link for zaza kind of indicated that things have changed in regard to datatyping in recent versions. Anytime things change new bugs (or "features") get introduced.

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  20. #20

    Thread Starter
    Frenzied Member zaza's Avatar
    Join Date
    Apr 2001
    Location
    Borneo Rainforest Habits: Scratching
    Posts
    1,486

    Re: Odd Round behaviour

    Yes, what I mean is that in any given operation which gets an evaluation, the default output is Integer unless there is something in the operation to coerce it differently.

    So in your example, (16 * 10000) cannot be evaluated even though v2 is Long.
    Similarly, CLng(1)+16*10000 also produces an overflow because the multiplication operator takes precedence over addition and hence that operation cannot be evaluated.
    However 1+16*CLng(10000) will evaluate.


    In tg's example, there are only addition operators so, as they all have equal parity, they are processed left-to-right.
    It's also why my example from earlier failed.
    Quote Originally Posted by zaza
    Code:
    Public Sub test()
        Dim x As Long
        x = 1    
        Debug.Print 32767 + 1 + x   
    End Sub
    Last edited by zaza; Mar 11th, 2012 at 11:19 AM.
    I use VB 6, VB.Net 2003 and Office 2010



    Code:
    Excel Graphing | Excel Timer | Excel Tips and Tricks | Add controls in Office | Data tables in Excel | Gaussian random number distribution (VB6/VBA,VB.Net) | Coordinates, Vectors and 3D volumes

  21. #21

    Thread Starter
    Frenzied Member zaza's Avatar
    Join Date
    Apr 2001
    Location
    Borneo Rainforest Habits: Scratching
    Posts
    1,486

    Re: Odd Round behaviour

    Well, I stand corrected.

    It does this in Office 2002 as well. I am quite surprised, but I guess it goes to show that it isn't as common an occurrence as I had feared.

    Cheers chaps.
    I use VB 6, VB.Net 2003 and Office 2010



    Code:
    Excel Graphing | Excel Timer | Excel Tips and Tricks | Add controls in Office | Data tables in Excel | Gaussian random number distribution (VB6/VBA,VB.Net) | Coordinates, Vectors and 3D volumes

  22. #22
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,687

    Re: [RESOLVED] Odd Round behaviour

    I guess I'm a little surprised too that more people in this thread haven't run into this before. I've dealt with a lot of financial-based systems over the years so this was something I ran to pretty early in my career. I guess it's something more common when $250,000 is chump change.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  23. #23
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: [RESOLVED] Odd Round behaviour

    Always used currency datatypes myself - so that's a longword with a 4-digit implied decimal point.

    [edit] back when I did vb6 [/edit]

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

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