[.net] VB.NET rounding issue

Started by
5 comments, last by alexmoura 17 years, 4 months ago
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

[size="2"]Don't talk about writing games, don't write design docs, don't spend your time on web boards. Sit in your house write 20 games when you complete them you will either want to do it the rest of your life or not * Andre Lamothe
Advertisement
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.
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?
[size="2"]Don't talk about writing games, don't write design docs, don't spend your time on web boards. Sit in your house write 20 games when you complete them you will either want to do it the rest of your life or not * Andre Lamothe
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.
doh, Kanato's right.
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.

[size="2"]Don't talk about writing games, don't write design docs, don't spend your time on web boards. Sit in your house write 20 games when you complete them you will either want to do it the rest of your life or not * Andre Lamothe
Quick comment -
new system.drawing.point(5) -> constructor call
new system.drawing.point(5){} -> array initialization with 6 positions

This topic is closed to new replies.

Advertisement