Printing uint64_t

Here's how I solved the problem of
printing 64 bit values as a string.
If there is an easier method I like to know?.

/******Testet on Arduino Due ******/
/*****  Testet on Arduino Uno *****/
byte i = 0;
byte ComBuffer[12];
String str;
uint64_t MaxValue = 18446744073709551615; // 8 bytes (2 ^ 64) - 1 max value
             
void setup() 
{
  Serial.begin(115200);
  Serial.println("Test for uint64_t to String."); // Test that program works
  Serial.flush();    
  str = ToString(MaxValue); // uint64_t to string
  Serial.println(str);
  Serial.flush();
}

void loop()
{  
  if( Serial.available() > 0 )
  {
      ComBuffer[i] = (byte)Serial.read();
      if (ComBuffer[i] == 13 )
      {
          if(ComBuffer[0] == 'p')
          {
             str = ToString(MaxValue); // uint64_t to string
             Serial.println(str);
          }          
          if(ComBuffer[0] == 'u')  // Test add 1 to number
          {             
               MaxValue = MaxValue + 1; 
               str = ToString(MaxValue); // uint64_t to string
               Serial.println(str);
          }
          if(ComBuffer[0] == 'd')  // Test subtract 1 from number
          {
              MaxValue = MaxValue - 1;
              str = ToString(MaxValue); // uint64_t to string
              Serial.println(str);
          }   
          i = ClearComBuffer();
      }          
      if(i == 11) // Prevent overflow of ComBuffer
          i = ClearComBuffer();            
      i++;
  }  
  
}  

String ToString(uint64_t x)
{
     boolean flag = false; // For preventing string return like this 0000123, with a lot of zeros in front.
     String str = "";      // Start with an empty string.
     uint64_t y = 10000000000000000000;
     int res;
     if (x == 0)  // if x = 0 and this is not testet, then function return a empty string.
     {
           str = "0";
           return str;  // or return "0";
     }    
     while (y > 0)
     {                
            res = (int)(x / y);
            if (res > 0)  // Wait for res > 0, then start adding to string.
                flag = true;
            if (flag == true)
                str = str + String(res);
            x = x - (y * (uint64_t)res);  // Subtract res times * y from x
            y = y / 10;                   // Reducer y with 10    
     }
     return str;
}  

int ClearComBuffer()
{ // clear com buffer for old data 
   for(int i = 0; i < 12; i++)
   {      
       ComBuffer[i] = 0;  
   }
   return -1;   
}

Well, if all you wish to do is print a 64-bit value -

void print(uint64_t value)
{
    if ( value >= 10 )
    {
        print(value / 10);
    }
    
    Serial.print(value % 10);
}

... and pray that you have a healthy amount of stack space available! :wink:

Hello and welcome,

Maybe something like this:

char * uintToStr( const uint64_t num, char *str )
{
  uint8_t i = 0;
  uint64_t n = num;
  
  do
    i++;
  while ( n /= 10 );
  
  str[i] = '\0';
  n = num;
 
  do
    str[--i] = ( n % 10 ) + '0';
  while ( n /= 10 );

  return str;
}

...

uint64_t num = 18446744073709551615ULL;
char str[21];
Serial.println( uintToStr( num, str ) );

Could be improved, I know.. :smiley_cat:

In lots of ways ...

#include <math.h>

void print(uint64_t value)
{
    const int NUM_DIGITS    = log10(value) + 1;

    char sz[NUM_DIGITS + 1];
    
    sz[NUM_DIGITS] =  0;
    for ( size_t i = NUM_DIGITS; i--; value /= 10)
    {
        sz[i] = '0' + (value % 10);
    }
    
    Serial.print(sz);
}

Oh, and no need to keep looking up the upper limit of a 64 bit number when you can simply have the compiler provide it by including 'limits.h' and using the constant

UINT64_MAX

Thanks for the many answers.
I testet all of your code on my Arduino Due board.

lloyddean you code will not compile this line, Serial.print(value % 10);
error: call of overloaded 'print(uint64_t)' is ambiguous?. and a long error list
You second proposal works great
Thanks for the infomation UINT64_MAX

guix code works great, i had to change your function to this to get it to compile.
String uintToStr( const uint64_t num, String str )

Yes, there are many ways to do this.

The code could be more efficient as it is not needed to both a DIV and a MOD.

size_t Print::println(int64_t number, int base)
{
    size_t n = 0;
    n += print(number, base);
    n += println();
    return n;
}

size_t Print::print(int64_t number, int base)
{
    size_t n = 0;
    if (number < 0)
    {
        write('-');
        number = -number;
        n++;
    }
    n += print((uint64_t)number, base);
    return n;
}

size_t Print::println(uint64_t number, int base)
{
    size_t n = 0;
    n += print((uint64_t)number, base);
    n += println();
    return n;
}

size_t Print::print(uint64_t number, int base)
{
    size_t n = 0;
    unsigned char buf[64];
    uint8_t i = 0;

    if (number == 0)
    {
        n += print((char)'0');
        return n;
    }

    if (base < 2) base = 2;
    else if (base > 16) base = 16;

    while (number > 0)
    {
        uint64_t q = number/base;
        buf[i++] = number - q*base;
        number = q;
    }

    for (; i > 0; i--)
    n += write((char) (buf[i - 1] < 10 ?
    '0' + buf[i - 1] :
    'A' + buf[i - 1] - 10));

    return n;
}

posted earlier version and discussion - Serial.print() of a 64-bit DOUBLE - Arduino Due - Arduino Forum -

joergenHansen:
lloyddean you code will not compile this line, Serial.print(value % 10);
error: call of overloaded 'print(uint64_t)' is ambiguous?. and a long error list

It's telling you that the print() function doesn't have a method to handle 64 bit parameters. Try casting to a byte:

Serial.print( (byte)(value % 10) );

I have a new question, working on my Arduino Due board.
I've read on the internet about sampling volts, to get a better resolution.
I think it was a document from microchip, that explained how this could be done.
Speed is not important.
I'd love to have your opinion on this code.

void setup() {
  analogReadResolution(12);
}
unsigned long SampleVolt()
{  // 12 bit to 14 bit 4 ^ 2 = 16  analogRead and div by 2 ^ 2 = 4
   // 12 bit to 15 bit 4 ^ 3 = 64  analogRead  and div by  2 ^ 3 = 8
   // 12 bit to 16 bit 4 ^ 4 = 256 analogRead  and div by  2 ^ 4 = 16
   unsigned long Volt = 0;
   for(int n = 0; n < 256; n++) 
   {
       delayMicroseconds(20);
       Volt = Volt + analogRead(A0);
   }   
   Volt = Volt / 16;  
   return Volt; // 16 bit value
}

I have tested on a machine that moves a potentiometer to different postions,
and then reading the new potentiometer value.
This gave me a better resolution???.

Google "oversampling" - what has this got to do with printing 64 bit integers?

That is NOT over-sampling, it is simply averaging a number of readings, which does absolutely nothing to improve accuracy or resolution. It simply creates more consistent readings.

Regards,
Ray L.

// 12 bit to 14 bit 4 ^ 2 = 16  analogRead and div by 2 ^ 2 = 4
   // 12 bit to 15 bit 4 ^ 3 = 64  analogRead  and div by  2 ^ 3 = 8
   // 12 bit to 16 bit 4 ^ 4 = 256 analogRead  and div by  2 ^ 4 = 16

The comment describes oversampling.

It's not my problem if the code fails to implement it.

AWOL:

// 12 bit to 14 bit 4 ^ 2 = 16  analogRead and div by 2 ^ 2 = 4

// 12 bit to 15 bit 4 ^ 3 = 64  analogRead  and div by  2 ^ 3 = 8
  // 12 bit to 16 bit 4 ^ 4 = 256 analogRead  and div by  2 ^ 4 = 16



The comment describes oversampling.

It's not my problem if the code fails to implement it.

Even the comments describe only averaging, and keeping several bits of noise to give the appearance of increased resolution (but it is still just noise...). Over-sampling requires sampling at a high sample rate, then applying extensive digital filtering to push the noise above the Nyquist limit so it doesn't affect the output.

Regards,
Ray L.

Some background reading

Thanks for the many interesting good answers.
So I have not achieved anything.
I might as well do this
for(int n = 0; n < 256; n++)
{ Volt = Volt + analogRead(A0); }
Volt = Volt / 256;

I read this website so what he claims are not true.

Best Regards
Your All.

My solution was to print them in hexidecimal. Then you just have to slice them in half first.

joergenHansen:
Here's how I solved the problem of
printing 64 bit values as a string.
If there is an easier method I like to know?.

Grab this: GitHub - krupski/Print: Improved Print functionality for Arduino (including stream support, print_P and related).

...and in your [b]arduinoxxxx/hardware/arduino/cores/arduino[/b] directory, replace "Print.h" and "Print.cpp" with the ones in the GitHub package.

The revised Print package adds features:

  • Printing a string with a newline automatically adds a CR (like it's supposed to).
  • You can print any size variable up to uint64_t (and int64_t).
  • Printing numbers no longer uses a buffer (a bit more free ram for you).
  • Provides "print_P", "println_P" (for printing PROGMEM strings)
  • Provides "print_E", "println_E" (for printing EEPROM strings)

Of course, be sure to backup your Print.cpp and Print.h files before replacing them with the new ones, and don't just rename them (for example, "oldPrint.cpp") because the Arduino IDE will find them and complain about duplicate definitions.

Hope this helps.

Nice Krupsi, but I think that code could benefit from using templates.. :stuck_out_tongue:

Also maybe you could make a pull request to the Arduino Github.