How to Print "uint64_t" or "ulong long" number ?

I'm newbie in C++
The Serial.print(ln) does not support 64 bit number. How can this be overwritten??

-> Test code on Wokwi ->

void setup() {

  Serial.begin(115200);

  uint8_t             a = -1; Serial.println("uint8_t:");
                              Serial.println(a);

  unsigned int        b = -1; Serial.println("\nunsigned int:");
                              Serial.println(b);
  uint16_t            c = -1; Serial.println("uint16_t:");
                              Serial.println(c);

  uint32_t            d = -1; Serial.println("\nuint32_t:");
                              Serial.println(d);
  unsigned long       e = -1; Serial.println("unsigned long:");
                              Serial.println(e);

  uint64_t            f = -1;
  unsigned long long  g = -1;

  uint64_t            billion =  1000000;
                      billion *= 1000000; // 1 metric-billion

  Serial.println("\nuint64_t:");
  Serial.print(uint32_t(f / billion));Serial.println(" * million^2");
  Serial.println("unsigned long long:");
  Serial.print(uint32_t(g / billion));Serial.println(" * million^2");
}

void loop() {}

See: data type - Print unsigned long long in ESP8266 - Arduino Stack Exchange
There are 2 examples there (for an ESP8266):

sprintf(dt,"%llu", t);
snprintf(dt, 18, "%llu", t);

You could write a print function yourself, starting from disaasemling an uint64 value to a two uint32

1 Like

@r-istvan

Have a look at - GitHub - RobTillaart/printHelpers: Arduino library to help formatting data for printing

Solution is not correct

It is not that simple, try 1000000000001 ULL

x will be 1 => print 1

And n-x => has a 1, and you loose all your leading zero's of the remainder.

The divider and remainder will always work.
This is just a small test. You see the "/" and the "%" that do the job:

void setup() 
{
  Serial.begin(115200);

  uint64_t x = 12345678901234567890ULL;
  printu64(x);

  printu64(123123ULL);
}

void loop() {}


void printu64(uint64_t t)
{
  // That are 20 decimal digits.
  char buffer[21] = "                    ";
  for(int i=19; i>=0 && t!=0ULL; i--)
  {
    buffer[i] = '0' + (t % 10);
    t /= 10;
  }
  Serial.println(buffer);
}

The remainder "% 10" grabs the most right decimal digit. The divider "/ 10" shifts the decimal number one digit to the right.

1 Like

There are few more serious errors here.
Firstly, it is obvious that in the second and third lines the result must be cast to the type unsigned long rather than long.
In addition, the size of the divisor in the first line is not selected correctly. It exceeds the unsigned long type limit, which means there is a possible overflow in the third line.

To test the error, try to print 1900000000000 ULL

@r-istvan
Overall, this example is no good at all. Do not mark it as "Solution"

It's works for me. Pls try -> Wokwi

void print64(uint64_t t) {

  char buffer[21] = "                    ";
  for(int i=19; i>=0 && t!=0ULL; i--) {
    buffer[i] = '0' + (t % 10);
    t /= 10;
  }

  String a = buffer;
  a.replace(" ", "");
  if (a == "") a = "0";

  Serial.println(a);
}

void setup() {
  Serial.begin(115200);

  // Max uint64_t : 18446744073709551615
  uint64_t n = -200;

  while (n > 200 or n < 200) {
    n++;
    print64(n);
  }
}

void loop() {}
1 Like

If it works, then it is good enough, but then again, it is not good enough.
It was just a small test to try it for myself :woozy_face:
The empty string of 20 spaces is hard to maintain. If you accidentally press delete while the cursor is there, then you get into a lot of trouble. It is better to use a library that is known to work well.

slightly modified version:

void print64(uint64_t t) {
  if ( t == 0) {Serial.println(t); return;}
  
  char buffer[21] = {0};
  for(int i=19; i>=0 && t!=0ULL; i--) {
    buffer[i] = '0' + (t % 10);
    t /= 10;
  }

  char* ptr = buffer;
 while (*ptr == 0) (ptr++;}
 
 Serial.println(ptr);
}
1 Like
void print64(uint64_t t) {

  char buffer[21] = "                    ";
  for(int i=19; i>=0 && t!=0ULL; i--) {
    buffer[i] = '0' + (t % 10);
    t /= 10;
  }
  String p = (buffer[19] == ' ' ? "0" : buffer);
  p.replace(" ", "");

  Serial.println(p);
}

void setup() {
  Serial.begin(115200);

  print64(0);
  print64(1);
  print64(2);
  print64(-1);
  print64(-101);
}

void loop() {}

The same problems as in #10. Read @Koepel #11 comment

The same problems as in #10. Read @Koepel #11 comment

And this ? -> Simulator


void print64(uint64_t n) {

  String t;

  if (n == 0) t = "0";
  else while (n) {
    uint8_t chr = (n % 10);
    t = String(chr) + t;
    n /= 10;
  }

  Serial.println(t);
}

void setup() {
  Serial.begin(115200);

  // uint64_t : 18446744073709551615

  print64(0);
  print64(1);
  print64(1000);
  print64(-1);
  print64(-101);
}

void loop() {}

Alright, I like it.
Some of use hesitate the use the String on a basic Arduino board. When something is added to a String, then there is a lot going on. A block of memory in the heap is released and a new block of memory is allocated.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.