none
Double Data Type (Generating All Numbers between 2 numbers) (Specified Step) RRS feed

  • Question

  • Greetings,

    I wrote a simple function to list all existing numbers between 2 numbers (Double Data type because it might not be always an integer number) (with specified +step) and populate a listbox with the numbers generated:

    Public Function Generate_Numbers(Start_NO As Double, End_NO As Double, sStep As Double,d_Listbox As ListBox)
     
            Dim j As Double = Start_NO
    
            Do While j < End_NO
    
                d_Listbox.Items.Add(j)
                j += sStep
    
            Loop
    
            d_Listbox.Items.Add(End_NO)
    
    
    
    Return Nothing
    
    End Function

    As a simple test, I call the function this way :

    Generate_Numbers(1,7,0.1,Listbox1)

    Here is the results (Listbox1's items) :

    1
    1.1
    1.2
    1.3
    1.4
    1.5
    1.6
    1.7
    1.8
    1.9
    2
    2.1
    2.2
    2.3
    2.4
    2.5
    2.6
    2.7
    2.8
    2.9
    3
    3.1
    3.2
    3.3
    3.4
    3.5
    3.6
    3.7
    3.8
    3.9
    4
    4.1
    4.2
    4.3
    4.4
    4.5
    4.6
    4.7
    4.8
    4.9
    5
    5.1
    5.2
    5.3
    5.4
    5.5
    5.6
    5.7
    5.8
    5.9
    6
    6.1
    6.19999999999999
    6.29999999999999
    6.39999999999999
    6.49999999999999
    6.59999999999999
    6.69999999999999
    6.79999999999999
    6.89999999999999
    6.99999999999999
    7

    As you can see, from 6.1 to 7 there are many decimal digits generated. NO IDEA! What could be the reason ?

    Friday, April 3, 2020 5:19 PM

Answers

  • Hello,

    I did a quickie which you might be able to adapt too.

    Public Class Form3
        Private Sub Form3_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            ListBox1.DataSource = Enumerable.Range(0, 201).
                Select(Function(x) x / 10D).Skip(10).
                Select(Function(item) CStr(item)).ToList()
        End Sub
    End Class


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    • Marked as answer by Kevin993 Friday, April 3, 2020 6:17 PM
    Friday, April 3, 2020 5:45 PM
    Moderator
  • Hi

    Double values can be confusing, The reason is that a computer can not represent numbers exactly and so when math operations are performed, the inaccuracy becomes apparent. The answer however is very straightforward - use the Decimal datatype instead.

    If you change to Decimal in all of your code you will find a more likeable presentation.

    Read this LINK (Decimal data type)

    Try this

    ' Form1 with ListBox1 and
    ' Button1
    Option Strict On
    Option Explicit On
    Public Class Form1
      Public Function Generate_Numbers(Start_NO As Decimal, End_NO As Decimal, sStep As Decimal) As List(Of Decimal)
        Dim d_Listbox As New List(Of Decimal)
        Dim j As Decimal = Start_NO
        Do While j < End_NO
          d_Listbox.Add(j)
          j += sStep
        Loop
        Return d_Listbox
      End Function
      Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim d As List(Of Decimal) = Generate_Numbers(1, 7, 0.1D)
        ListBox1.DataSource = d
      End Sub
    End Class


    Regards Les, Livingston, Scotland


    • Edited by leshay Friday, April 3, 2020 5:51 PM
    • Marked as answer by Kevin993 Friday, April 3, 2020 6:17 PM
    Friday, April 3, 2020 5:49 PM
  • Hi Kevin,

    Please just use Math.Round method to rounds a value to the nearest integer

    d_Listbox.Items.Add(Math.Round(j, 2, MidpointRounding.AwayFromZero))
    Public Function Generate_Numbers(Start_NO As Double, End_NO As Double, sStep As Double, d_Listbox As ListBox)
    
            Dim j As Double = Start_NO
    
            Do While j < End_NO
    
                d_Listbox.Items.Add(Math.Round(j, 2, MidpointRounding.AwayFromZero))
                j += sStep
    
            Loop
    
            'd_Listbox.Items.Add(End_NO)
    
    
            Return Nothing
    
    End Function



    The result

    1
    1.1
    1.2
    1.3
    1.4
    1.5
    1.6
    1.7
    1.8
    1.9
    2
    2.1
    2.2
    2.3
    2.4
    2.5
    2.6
    2.7
    2.8
    2.9
    3
    3.1
    3.2
    3.3
    3.4
    3.5
    3.6
    3.7
    3.8
    3.9
    4
    4.1
    4.2
    4.3
    4.4
    4.5
    4.6
    4.7
    4.8
    4.9
    5
    5.1
    5.2
    5.3
    5.4
    5.5
    5.6
    5.7
    5.8
    5.9
    6
    6.1
    6.2
    6.3
    6.4
    6.5
    6.6
    6.7
    6.8
    6.9
    7
    
    if you comment or remove this part (d_Listbox.Items.Add(End_NO))  the last number will not be duplicate 


    Please remember to mark the replies as answers if they helped you :) ~



    • Edited by Rebin Qadir Friday, April 3, 2020 6:20 PM
    • Marked as answer by Kevin993 Friday, April 3, 2020 6:21 PM
    Friday, April 3, 2020 6:12 PM

All replies

  • Hello,

    I did a quickie which you might be able to adapt too.

    Public Class Form3
        Private Sub Form3_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            ListBox1.DataSource = Enumerable.Range(0, 201).
                Select(Function(x) x / 10D).Skip(10).
                Select(Function(item) CStr(item)).ToList()
        End Sub
    End Class


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    • Marked as answer by Kevin993 Friday, April 3, 2020 6:17 PM
    Friday, April 3, 2020 5:45 PM
    Moderator
  • Hi

    Double values can be confusing, The reason is that a computer can not represent numbers exactly and so when math operations are performed, the inaccuracy becomes apparent. The answer however is very straightforward - use the Decimal datatype instead.

    If you change to Decimal in all of your code you will find a more likeable presentation.

    Read this LINK (Decimal data type)

    Try this

    ' Form1 with ListBox1 and
    ' Button1
    Option Strict On
    Option Explicit On
    Public Class Form1
      Public Function Generate_Numbers(Start_NO As Decimal, End_NO As Decimal, sStep As Decimal) As List(Of Decimal)
        Dim d_Listbox As New List(Of Decimal)
        Dim j As Decimal = Start_NO
        Do While j < End_NO
          d_Listbox.Add(j)
          j += sStep
        Loop
        Return d_Listbox
      End Function
      Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim d As List(Of Decimal) = Generate_Numbers(1, 7, 0.1D)
        ListBox1.DataSource = d
      End Sub
    End Class


    Regards Les, Livingston, Scotland


    • Edited by leshay Friday, April 3, 2020 5:51 PM
    • Marked as answer by Kevin993 Friday, April 3, 2020 6:17 PM
    Friday, April 3, 2020 5:49 PM
  • Hi Kevin,

    Please just use Math.Round method to rounds a value to the nearest integer

    d_Listbox.Items.Add(Math.Round(j, 2, MidpointRounding.AwayFromZero))
    Public Function Generate_Numbers(Start_NO As Double, End_NO As Double, sStep As Double, d_Listbox As ListBox)
    
            Dim j As Double = Start_NO
    
            Do While j < End_NO
    
                d_Listbox.Items.Add(Math.Round(j, 2, MidpointRounding.AwayFromZero))
                j += sStep
    
            Loop
    
            'd_Listbox.Items.Add(End_NO)
    
    
            Return Nothing
    
    End Function



    The result

    1
    1.1
    1.2
    1.3
    1.4
    1.5
    1.6
    1.7
    1.8
    1.9
    2
    2.1
    2.2
    2.3
    2.4
    2.5
    2.6
    2.7
    2.8
    2.9
    3
    3.1
    3.2
    3.3
    3.4
    3.5
    3.6
    3.7
    3.8
    3.9
    4
    4.1
    4.2
    4.3
    4.4
    4.5
    4.6
    4.7
    4.8
    4.9
    5
    5.1
    5.2
    5.3
    5.4
    5.5
    5.6
    5.7
    5.8
    5.9
    6
    6.1
    6.2
    6.3
    6.4
    6.5
    6.6
    6.7
    6.8
    6.9
    7
    
    if you comment or remove this part (d_Listbox.Items.Add(End_NO))  the last number will not be duplicate 


    Please remember to mark the replies as answers if they helped you :) ~



    • Edited by Rebin Qadir Friday, April 3, 2020 6:20 PM
    • Marked as answer by Kevin993 Friday, April 3, 2020 6:21 PM
    Friday, April 3, 2020 6:12 PM
  • Double values can be confusing, The reason is that a computer can not represent numbers exactly and so when math operations are performed, the inaccuracy becomes apparent


    Regards Les, Livingston, Scotland


    I was completely unaware of that! I knew that there is possibility of error or inaccuracy in some specific math operations, but I didn't expect to encounter operation inaccuracy adding 0.1 to numbers of a range!

    Anyway, Thanks for the info you provided.

    Friday, April 3, 2020 6:21 PM
  • Hi Kevin,

    Please just use Math.Round method to rounds a value to the nearest integer

    d_Listbox.Items.Add(Math.Round(j, 2, MidpointRounding.AwayFromZero))
    Public Function Generate_Numbers(Start_NO As Double, End_NO As Double, sStep As Double, d_Listbox As ListBox)
    
            Dim j As Double = Start_NO
    
            Do While j < End_NO
    
                d_Listbox.Items.Add(Math.Round(j, 2, MidpointRounding.AwayFromZero))
                j += sStep
    
            Loop
    
            'd_Listbox.Items.Add(End_NO)
    
    
            Return Nothing
    
    End Function



    The result

    1
    1.1
    1.2
    1.3
    1.4
    1.5
    1.6
    1.7
    1.8
    1.9
    2
    2.1
    2.2
    2.3
    2.4
    2.5
    2.6
    2.7
    2.8
    2.9
    3
    3.1
    3.2
    3.3
    3.4
    3.5
    3.6
    3.7
    3.8
    3.9
    4
    4.1
    4.2
    4.3
    4.4
    4.5
    4.6
    4.7
    4.8
    4.9
    5
    5.1
    5.2
    5.3
    5.4
    5.5
    5.6
    5.7
    5.8
    5.9
    6
    6.1
    6.2
    6.3
    6.4
    6.5
    6.6
    6.7
    6.8
    6.9
    7
    
    if you comment or remove this part (d_Listbox.Items.Add(End_NO))  the last number will not be duplicate 


    Please remember to mark the replies as answers if they helped you :) ~



    Thanks for writing down. Right, but if you ask me , I really have no idea if it always rounds correctly the same way it does in the limited range we are talking about. leshay scared me!
    Friday, April 3, 2020 6:23 PM
  • Hello,

    I did a quickie which you might be able to adapt too.

    Public Class Form3
        Private Sub Form3_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            ListBox1.DataSource = Enumerable.Range(0, 201).
                Select(Function(x) x / 10D).Skip(10).
                Select(Function(item) CStr(item)).ToList()
        End Sub
    End Class


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Thanks Karen. Another successful demonstration of using Select and functions.

    Friday, April 3, 2020 6:26 PM
  • > I didn't expect to encounter operation inaccuracy adding 0.1 to numbers of a range!

    You should.  The issue is that the decimal number 0.1 cannot be represented exactly in binary, just like the number 1/3 cannot be represented exactly in decimal.  0.1 in binary is an infinitely repeating value, 0.000110011001100110011...  In a double-precision float, you'll get 53 bits of that fraction, which is very close to 0.1, but it's not exactly 0.1.  In a single-precision float, the closest you can come to 0.1 is 0.10000000149011612, which is just a bit high.  In a double, it happens to be just a bit low.

    The programmer needs to be aware of this, but don't try to fight it.  The key is to leave the values in their native (approximate) state internally, but when you need to show them to humans, you round them to whatever your application needs.


    Tim Roberts | Driver MVP Emeritus | Providenza &amp; Boekelheide, Inc.

    Friday, April 3, 2020 6:38 PM