News:

Let's find out together what makes a PIC Tick!

Main Menu

Printing large numbers with comma seperator

Started by See_Mos, Feb 24, 2026, 01:19 PM

Previous topic - Next topic

See_Mos

Help please, I am definitely losing the plot.  I have done this a long time ago but cannot remember how or find the old code.

All I need to do is print a DWord variable with comma separators so 123456789 shows on the LCD as 123,456,789.

RGV250

Hi,
I can't try at the moment but converting to string and using mid$ etc is my guess.

Bob

See_Mos

I'm not alone then?

I get the correct display with this but I am sure there is a neater way.

Dim Big_number As Dword
Dim P1 As Dword
Dim P2 As Dword
Dim P3 As Dword

    Big_number = 980650320
    Print At 1,1,Dec Big_number   
    P1 = Big_number // 1000
    P2 = Big_number / 1000
    P2 = P2 //1000
    P3 = Big_number /1000000

    Print At 3,1,Dec3 P3,",",Dec3 P2,",",Dec3 P1 



top204

#3
That is the way I always display values that require comma or decimal point delimiters.

It can be done with String variable manipulation, but division and remainder is the nicest method.

Below is a code listing I've just created, which is, essentially, the same as your method:

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes pValue PIC Tick!
'
' Transmit delimited values to a serial terminal.
'
' Written for the Positron8 compiler by Les Johnson.
' https://sites.google.com/view/rosetta-tech/positron-compilers-experimenters-notebook
'
    Device = 18F25K20                                                   ' Tell the compiler what device to compile for
    Declare Xtal = 16                                                   ' Tell the compiler what frequency the device will be operating at (in MHz)
    Declare Auto_Heap_Strings = On                                      ' Tell the compiler to create Strings above standard variables, so assembler code is more efficient
    Declare Auto_Variable_Bank_Cross = On                               ' Tell the compiler to create any multi-byte variables in the same RAM bank. For more efficiency
'
' Setup USART1
'
    Declare Hserial_Baud = 9600                                         ' Set the Baud rate to 9600
    Declare HRSOut1_Pin  = PORTC.6                                      ' Set the TX pin
'
' Create Global variables here
'
    Dim MyDWord As Dword
   
'-------------------------------------------------------------------------------------------------------------
' The main program starts here
' Transmit delimited values to a serial terminal
'
Main:
    MyDWord = 12
    HRSOut1Ln Dec MyDWord, "        is ", CommaDelim(MyDWord)
   
    MyDWord = 123
    HRSOut1Ln Dec MyDWord, "       is ", CommaDelim(MyDWord)

    MyDWord = 1234
    HRSOut1Ln Dec MyDWord, "      is ", CommaDelim(MyDWord)
   
    MyDWord = 12345
    HRSOut1Ln Dec MyDWord, "     is ", CommaDelim(MyDWord)
   
    MyDWord = 123456
    HRSOut1Ln Dec MyDWord, "    is ", CommaDelim(MyDWord)
   
    MyDWord = 1234567
    HRSOut1Ln Dec MyDWord, "   is ", CommaDelim(MyDWord)
   
    MyDWord = 12345678
    HRSOut1Ln Dec MyDWord, "  is ", CommaDelim(MyDWord)

    MyDWord = 123456789
    HRSOut1Ln Dec MyDWord, " is ", CommaDelim(MyDWord)

'-------------------------------------------------------------------------------------------------------------
' Comma delimit an integer value
' Input     : pValue holds the value to convert to a delimited string
' Output    : Returns the comma delimited String
' Notes     : None
'
Proc CommaDelim(pValue As Dword), String * 20
    Result = Str$(Dec, pValue / 1000000) + "," + Str$(Dec, (pValue // 1000000) / 1000) + "," + Str$(Dec, pValue // 1000)      
EndProc

On the serial terminal, it will display:

12        is 0,0,12
123       is 0,0,123
1234      is 0,1,234
12345     is 0,12,345
123456    is 0,123,456
1234567   is 1,234,567
12345678  is 12,345,678
123456789 is 123,456,789


Beginning 0 values can be eliminated in the procedure by using a temporary variable for the divisions, and only adding the value and comma to the Result if it is not 0 etc, such as in the simple procedure listed below:

'-------------------------------------------------------------------------------------------------------------
' Comma delimit an integer value
' Input     : pValue holds the value to convert to a delimited string
' Output    : Returns the comma delimited String
' Notes     : Eliminates leading zeroes
'
Proc CommaDelim(pValue As Dword), String * 20
    Dim dTemp As Dword

    Clear Result
    If pValue = 0 Then
        Result = "0"
        ExitProc
    EndIf
       
    dTemp = pValue / 1000000
    If dTemp > 0 Then
        Result = Result + Str$(Dec, dTemp) + ","
    EndIf
    
    dTemp = (pValue // 1000000) / 1000
    If dTemp > 0 Then
        Result = Result + Str$(Dec, dTemp) + ","
    EndIf
  
    dTemp = pValue // 1000
    If dTemp > 0 Then
        Result = Result + Str$(Dec, dTemp)
    EndIf
EndProc

And on the serial terminal, it will display:

12        is 12
123       is 123
1234      is 1,234
12345     is 12,345
123456    is 123,456
1234567   is 1,234,567
12345678  is 12,345,678
123456789 is 123,456,789


Regards
Les

Pepe

demo proteus

See_Mos

Thanks Les, that is what I was trying to remember.  The other that I was thinking of was the DIG command which I used with the MAX7219.  I think the R_Val could easily be converted to ASCII but this idea is a bit more messy.

Display:
        Digit = 0                                    ' Start at Digit 0 of Max_Disp Variable
        For Position = 1 To 6                        ' Start at Farthest Right of Display       
        Register = Position                            ' Place Position into Register
        R_Val = Dig Max_Disp,Digit                    ' Extract the individual numbers from Max_Disp           
        If Max_Disp < 10 And Position = 2 Then R_Val = 15    ' Zero Suppression for the Second digit
        If Max_Disp < 100 And Position = 3 Then R_Val = 15    ' Zero Suppression for the Third digit
        If Max_Disp < 1000 And Position = 4 Then R_Val = 15    ' Zero Suppression for the Fourth digit
        If Max_Disp < 10000 And Position = 5 Then R_Val = 15' Zero Suppression for the Fifth digit
        If Max_Disp < 100000 And Position = 6 Then R_Val = 15
        If Digit = Max_Dp Then R_Val.7 = 1            ' Place the decimal point, held in Max_DP
        GoSub Transfer                                ' Transfer the 16-bit Word to the MAX7219
        If Digit >= 6 Then Digit = 0                ' We only need the first four digits
        Digit = Digit + 1                            ' Point to next Digit within Max_Disp
        Next                                        ' Close the Loop
        Return                                        ' Exit from subroutine

' Send a 16-bit word to the MAX7219
Transfer:
          SHOut Dta,Clk,MsbFirst,[Register,R_Val]    ' Shift Out the Register first, then the data
        Load = 1                                    ' The data is now acted upon
        DelayUS 5                                    ' A small delay to ensure correct clocking times               
        Load = 0                                    ' Disable the MAX7219
        Return                                        ' Exit from Subroutine

top204

#6
The Dig function comes in handy if a single digit is required to be extacted from an integer value, however, to use it to build a String would be very wasteful, and rather slow. :-)

I used the Dig function many, many years ago, in my melabs book (2001) for interfacing with a MAX7219 device, because they were almost magical devices at the time, and the melabs compiler was very limited in what it could do, and variable size etc... :-) However, the Dig function is still one of the best methods of extracting digits from a value for that type of display, and I used it in my Proton MAX7219 code, a few years ago.

Below is a code listing for an improved procedure to convert an integer into a comma delimited String, that also accepts signed values:

'-------------------------------------------------------------------------------------------------------------
' Comma delimit a signed or unsigned integer value, with zero blanking
' Input     : pValue holds the value to convert to a delimited string (maximum is a 9-digit integer value)
' Output    : Returns the zero blanked comma delimited String
' Notes     : None
'
Proc CommaDelim(pValue As Dword), String * 20
    Dim dTemp As Dword                                      ' A temporary variable for divisions
  
    Clear Result                                            ' Clear the Result String
    If pValue = 0 Then                                      ' Is pValue 0?
        Result = "0"                                        ' Yes. So return a String of "0"
        ExitProc                                            ' Exit the procedure
    ElseIf pValue.SDword < 0 Then                           ' Is pValue a negative value?
        pValue = Abs(pValue)                                ' Yes. So make the value unsigned
        Result = "-"                                        ' Add a sign character to the start of the Result String
    EndIf  
      
    dTemp = pValue / 1000000                                ' Divide pValue to get the hundred millions
    If dTemp > 0 Then                                       ' Is dTemp greater than 0?
        Result = Result + Str$(Dec, dTemp) + ","            ' Yes. So convert the integer to ASCII in the Result String
    EndIf
    
    dTemp = (pValue // 1000000) / 1000                      ' Divide and Modulus pValue to get the hundred thousands
    If dTemp > 0 Then                                       ' Is dTemp greater than 0?
        Result = Result + Str$(Dec, dTemp) + ","            ' Yes. So convert the integer to ASCII in the Result String
    EndIf
  
    dTemp = pValue // 1000                                  ' Modulus pValue to get the thousands
    If dTemp > 0 Then                                       ' Is dTemp greater than 0?
        Result = Result + Str$(Dec, dTemp)                  ' Yes. So convert the integer to ASCII in the Result String
    EndIf
EndProc

On a serial terminal, adding a sign to the previous values in the demo, displays:

-12        is -12
-123       is -123
-1234      is -1,234
-12345     is -12,345
-123456    is -123,456
-1234567   is -1,234,567
-12345678  is -12,345,678
-123456789 is -123,456,789


Regards
Les