Sign in to follow this  
daviangel

[.net] VB.NET rounding issue

Recommended Posts

Can anyone explain why 26/2 =14 in VB? At least that's what this piece of code is insisting on under VB2005: specifically this line: Dim curvePoints(coords.Length / 2) As Point keeps making my point array 14 instead of 13 as you would think. I also have the same code in C# and under C# it returns 13 as it should.

Function drawCurve(ByVal e As Graphics, ByVal coords() As Single) As String


        Dim curvePen As New Pen(Color.DarkBlue, 2)
        'Create a Point array
        Dim curvePoints(coords.Length / 2) As Point ' needed to add -1 here due to weird VB rounding-jmm!

        Dim cmsg As String = ""

        'Multiply by 10 to increase precision
        Dim ctr As Integer = 0
        While ctr < coords.Length - 1
            cmsg += " (" + coords(ctr).ToString() + "," + coords(ctr).ToString() + ")"
            '6.5 becomes 65, for example
            coords(ctr) = coords(ctr) * GRID
            ctr += 1
        End While

        'Populate the Point array with coordinate values
        ctr = 0
        While ctr < coords.Length - 1
            'One Point object for each two coordinate values         
            curvePoints(CInt((ctr / 2))) = New Point(CENTER + CInt(coords(ctr)), CENTER - CInt(coords((ctr + 1))))
            'x value
            'y value
            ctr += 2 'get sets of 2
        End While
        'Draw curve to the chart
        e.DrawCurve(curvePen, curvePoints)

        Return cmsg

    End Function

Share this post


Link to post
Share on other sites
Are you sure coords length is 26 and not 27? VB does banker's rounding rather than truncation - that means that if the divided number falls on a .5, it gets rounded to the nearest even number, not truncated to the lowest one. If you want truncation, you can use the int() function, that will truncate your division.
(Btw, if the coords array was defined as "new single(26){}", or dim coords(26) as single, that array has 27 elements. VB array initializations takes the upper bound of the array, not the number of elements)

As a curiosity, the idea behind banker's rounding is that rounding errors tend to cancel each other out, instead of tending to accumulate one way or the other.

Share this post


Link to post
Share on other sites
Quote:
Original post by alexmoura
Are you sure coords length is 26 and not 27? VB does banker's rounding rather than truncation - that means that if the divided number falls on a .5, it gets rounded to the nearest even number, not truncated to the lowest one. If you want truncation, you can use the int() function, that will truncate your division.
(Btw, if the coords array was defined as "new single(26){}", or dim coords(26) as single, that array has 27 elements. VB array initializations takes the upper bound of the array, not the number of elements)

As a curiosity, the idea behind banker's rounding is that rounding errors tend to cancel each other out, instead of tending to accumulate one way or the other.

Yeah I thought about that too at first but I just ran through the debugger again and it's still showing coords.length as 26 not 27. So how can rounding even apply to 26/2 since there is no fractional part?

Share this post


Link to post
Share on other sites
The problem isn't rounding, you're effectively doing:

dim curvePoints(13) as Point

In VB, this creates an array with 14 members, numbered from 0 to 13.

Share this post


Link to post
Share on other sites
Doh the array off by 1 error strikes again!
In previous versions of VB the first element started at 1 not 0 so it's a common mistake to make.
Not to mention the syntax is backwards compared to C#.
Looking at the original C# code I was trying to convert it's easy to see now the problem.
The original C# array didn't specify a dimension and put 13 points in curvePoints which became curvePoints[12] with 13 elements from 0-12.
My VB array is creating curvePoints[13] with 14 elements from 0-13 hence the extra 1.


//Create a Point array
Point[] curvePoints = new Point[coords.Length / 2];

Ok and now I rember why I didn't just do it this way in vb in the first place:
Dim curvePoints() As Point = New Point(CInt(coords.Length / 2))
because vb was giving this error:
Error 1 Value of type 'System.Drawing.Point' cannot be converted to '1-dimensional array of System.Drawing.Point'.
and I just figured out why it wanted this
Dim curvePoints() As Point = New Point(CInt(coords.Length / 2)) {}
missed the braces at end!
Actually I just ran through the debugger again and I guess VB array intitializations take the upper bound as alexmoura said.
Since in C# the code above creates an array of 13 points with curvepoints dimension 13 with elements 0-12 whereas the identical VB code creates an array of 14 points with curvepoints 0-13.
I guess I'll have to look more into how VB array initilizations since I thought I knew how they worked.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this