How to convert integers to human readable numbers from a function parser

Mattia Fanti 356 Reputation points
2022-02-21T19:36:38.967+00:00

Hi, I'm parsing this API

deserializing to a module with the code:

 Public Class Result  
        Public Property asks As String()()  
        Public Property bids As String()()  
        Public Property seqNum As Integer  
        Public Property prevSeqNum As Integer  
        Public Property lastTs As Double  
    End Class  
    Public Class Root  
        Public Property [error] As Object  
        Public Property result As Result  
        Public Property id As Integer  
    End Class  
  
    Private URI As String = API URL  
  
    Private Async Function GetJsonFromApi() As Task(Of Root)  
  
        Using http As New HttpClient(),  
                  response As HttpResponseMessage = Await http.GetAsync(URI)  
  
            Return JsonConvert.DeserializeObject(Of Root)(Await response.Content.ReadAsStringAsync())  
        End Using  
    End Function  
    Private Sub OutputAsks(asks As String()())  
        'asks  
        Try  
            Dim contents As New StringBuilder  
            For Each ask In asks  
                contents.AppendLine(String.Join(" - ", ask))  
            Next  
  
            RichTextBox1.BeginInvoke(Sub()  
                                         RichTextBox1.Text = contents.ToString()  
                                         RichTextBox1.Lines = RichTextBox1.Lines.  
                Where(Function(x) Not String.IsNullOrEmpty(x)).  
                OrderByDescending(Function(x) Decimal.Parse(x.Split(" "c)(0))).ToArray  
                                         ScrollToBottom(RichTextBox1)  
                                     End Sub)  
        Catch ex As Exception  
        End Try  
    End Sub  
  
    Private Sub OutputBids(bids As String()())  
        'bids  
        Try  
            Dim contents As New StringBuilder  
            For Each bid In bids  
  
                contents.AppendLine(String.Join(" - ", bid))  
            Next  
  
            RichTextBox2.BeginInvoke(Sub()  
                                         RichTextBox2.Text = contents.ToString()  
                                     End Sub)  
        Catch ex As Exception  
        End Try  
    End Sub  

and I'm getting this correct output:
176542-immagine-2022-02-21-202828.jpg

now, I'm using a function to make integers human readable, with this working code:

 Public Shared Function ToKMB(ByVal num As Double) As String  
        If num > 999999999 OrElse num < -999999999 Then  
            Return num.ToString("0,,,.###B", CultureInfo.InvariantCulture)  
        ElseIf num > 999999 OrElse num < -999999 Then  
            Return num.ToString("0,,.##M", CultureInfo.InvariantCulture)  
        ElseIf num > 999 OrElse num < -999 Then  
            Return num.ToString("0,.#K", CultureInfo.InvariantCulture)  
        Else  
            Return num.ToString(CultureInfo.InvariantCulture)  
        End If  
    End Function  
  

This function is working everywhere but in Private Sub OutputAsks and Private Sub Outputbids.
I've tried with

For Each bid In bids  
  
                contents.AppendLine(String.Join(" - ", ToKMB(bid)))  
            Next  
  

in both asks and bids private subs, but I'm getting an error which can't be solved with intellisense ( I also have option strict on .. )
Error: Value of type 'String()' cannot be converted to 'Double'.

I basically want to formatting only the "Quantity" integers with the function ToKMB .
like :
"0.00001080 - 340.2K" and so on
Many Thanks

VB
VB
An object-oriented programming language developed by Microsoft that is implemented on the .NET Framework. Previously known as Visual Basic .NET.
2,713 questions
0 comments No comments
{count} votes

Accepted answer
  1. LesHay 7,126 Reputation points
    2022-02-22T00:33:45.937+00:00

    Hi
    This is a fully working version. The results as shown below using the code below the image. There are a couple of changes, including putting a MessageBox into each of the Try....Catch blocks (you are not doing yourself any favours by throwing away exceptions). You didn't say what the Timer1 interval is so I just used added a Timer1.Stop so I would only get one pass of data.

    176611-111.png

    Option Strict On  
    Option Explicit On  
    Imports System.Net.Http  
    Imports System.Runtime.InteropServices  
    Imports System.Text  
    Imports Newtonsoft.Json  
      
    Public Class Form1  
      <DllImport("user32.dll", CharSet:=CharSet.Auto)>  
      Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr  
      End Function  
      
      Private Const WM_VSCROLL As Integer = 277  
      Private Const SB_PAGEBOTTOM As Integer = 7  
      Friend Shared Sub ScrollToBottom(ByVal richTextBox As RichTextBox)  
        SendMessage(richTextBox.Handle, WM_VSCROLL, CType(SB_PAGEBOTTOM, IntPtr), IntPtr.Zero)  
        richTextBox.SelectionStart = richTextBox.Text.Length  
      End Sub  
      Public Class Result  
        Public Property asks As String()()  
        Public Property bids As String()()  
        Public Property seqNum As Integer  
        Public Property prevSeqNum As Integer  
        Public Property lastTs As Double  
      End Class  
      Public Class Root  
        Public Property [error] As Object  
        Public Property result As Result  
        Public Property id As Integer  
      End Class  
      Private URI As String = "https://api.hotbit.io/api/v1/order.depth?market=KIBA/USDT&limit=150&interval=1e-8"  
      
      Private Async Function GetJsonFromApi() As Task(Of Root)  
      
        Using http As New HttpClient(),  
                      response As HttpResponseMessage = Await http.GetAsync(URI)  
      
          Return JsonConvert.DeserializeObject(Of Root)(Await response.Content.ReadAsStringAsync())  
        End Using  
      End Function  
      Private Sub OutputAsks(asks As String()())  
        'asks  
        Try  
          Dim contents As New StringBuilder  
          For Each ask() As String In asks  
      
            contents.AppendLine(String.Join(" - ", {ask(0), ToKMB(GetDouble(ask(1)))}))  
          Next  
      
          RichTextBox1.BeginInvoke(Sub()  
                                     RichTextBox1.Text = contents.ToString()  
                                     RichTextBox1.Lines = RichTextBox1.Lines.  
                    Where(Function(x) Not String.IsNullOrEmpty(x)).  
                    OrderByDescending(Function(x) Decimal.Parse(x.Split(" "c)(0))).ToArray  
                                     ScrollToBottom(RichTextBox1)  
                                   End Sub)  
        Catch ex As Exception  
          MessageBox.Show("ERROR in asks")  
        End Try  
      End Sub  
      Private Sub OutputBids(bids As String()())  
        'bids  
        Try  
          Dim contents As New StringBuilder  
          For Each Bid() As String In bids  
      
            contents.AppendLine(String.Join(" - ", {Bid(0), ToKMB(GetDouble(Bid(1)))}))  
      
          Next  
      
          RichTextBox2.BeginInvoke(Sub()  
                                     RichTextBox2.Text = contents.ToString()  
                                   End Sub)  
        Catch ex As Exception  
          MessageBox.Show("ERROR in Bids")  
        End Try  
      End Sub  
      Public Shared Function ToKMB(num As Double) As String  
        If num > 999999999 OrElse num < -999999999 Then  
          Return num.ToString("0,,,.###B", Globalization.CultureInfo.InvariantCulture)  
        ElseIf num > 999999 OrElse num < -999999 Then  
          Return num.ToString("0,,.##M", Globalization.CultureInfo.InvariantCulture)  
        ElseIf num > 999 OrElse num < -999 Then  
          Return num.ToString("0,.#K", Globalization.CultureInfo.InvariantCulture)  
        Else  
          Return num.ToString("#.00", Globalization.CultureInfo.InvariantCulture)  
        End If  
      End Function  
      Function GetDouble(s As String) As Double  
        Dim v As Double = 0.0D  
        If Double.TryParse(s, v) Then Return v  
        Return 0.0D  
      End Function  
      Private Async Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick  
        Dim root As Root = Await GetJsonFromApi()  
        OutputAsks(root.result.asks)  
        OutputBids(root.result.bids)  
    
    
      ' only one pass for this test  
       Timer1.Stop()  
    
      End Sub  
      Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click  
        Timer1.Start()  
      End Sub  
    End Class  
    
    1 person found this answer helpful.

7 additional answers

Sort by: Most helpful
  1. LesHay 7,126 Reputation points
    2022-02-21T20:32:35.713+00:00

    Hi

    Looks like you are trying to pass 'bid' or 'ask', which are Strings to the ToKMB function. However, the function parameter requires a Double.


  2. LesHay 7,126 Reputation points
    2022-02-21T20:51:32.523+00:00

    Hi

    Maybe, try this. Add the Function below to your code, and where you are calling your function try calling it via my function - like this ToKMB(GetDouble(Bid))

    Function GetDouble(s As String) As Double
            Dim v As Double = 0.0D
            If Double.TryParse(s, v) Then Return v
            Return 0.0D
        End Function
    

  3. LesHay 7,126 Reputation points
    2022-02-21T21:07:40.04+00:00

    Hi
    I can't use your code, as it would be full of unknown variables etc.

    First of all, are we talking about the same problem?
    As I understand it, you are trying to get your Function ToKMB to return a string. The function requires a Double to be passed to it. I think you are passing a string - in that case, things will not work.

    Another thing, please show the actual value of 'bid' that is being passed to the ToKMB function.

    Instead, I have suggested you add another Function called GetDouble, which I posted in my last reply.

    Once you have added that new function, then change your existing line:

    contents.AppendLine(String.Join(" - ", ToKMB(GetDouble(bid))))
    

  4. LesHay 7,126 Reputation points
    2022-02-21T21:31:37.667+00:00

    Hi

    Yes, but have you actually examined the value that is being passed to your ToKMB function. OK, it is a string, but what does the string contain eg "0.00789" etc?

    Are you suggesting that the code you posted in first post is a stand alone working code that I should be able to copy/paste and have a working version of what you have? Afraid not! Try starting a new project, copy/paste the code you posted, ork out what Includes needed, guess what API URL is ..... etc ........... etc ............ etc.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.