limitations of Math on the Due

Hello

I was trying to do this calculation on the due,

((51539607540 + 2969567055 + 15925005 + 34816 + 169) / 144000000) = 378

but the due doe not like it, outputs zero rather than 378

is there a math limitation or is there an additional library that i should use

regards

Jeff

The Due will use 32 bit integers if you don't tell it any differently as it is a 32 bit processor. 51,539,607,540 requires more than 32 bits to store (you only get up to about 4 billion if you use unsigned integers, 2 billion for signed). But, you can force the use of 64 bit integers which should then give you the result you are looking for.

((51539607540LL + 2969567055LL + 15925005LL + 34816LL + 169LL) / 144000000LL)

That is, put two L's after each numeric literal to force it to be long long which should be 64 bits.

Thanks

LL seems to work fine,

// init
long long parm1 = 0;
long long parm2 = 0;
long long parm3 = 0;
long long parm4 = 0;
long long parm5 = 0;
long long parm6 = 0;
unsigned int parm7 = 0;

//example values 12,180,207,29,41
//124294967295 + 1806777215 + 20765535 + 29256 + 41 =
// 51539607540 +1219898700 + 13565745 + 7424 + 41 = 52773079450
// 52773079450/144000000 = 366.47 (the due got 349)

//assign
parm1 = head_readback[7] * 4294967295;
parm2 = head_readback[8] * 16777215;
parm3 = head_readback[9] * 65535;
parm4 = head_readback[10] * 256;

//calc
parm5 = parm5 + parm1;
parm5 = parm5 + parm2;
parm5 = parm5 + parm3;
parm5 = parm5 + parm4;
parm5 = parm5 + head_readback[11];

parm6 = parm5/144000000; //
parm7 = (unsigned int) parm6;

// display
Serial.print(parm7);

regards

Jeff

Few observations:

  1. ((51539607540 + 2969567055 + 15925005 + 34816 + 169) / 144000000)
    is evaluated to 378.6467679513889 (manual computation) and not into 378.

  2. declaring the given data as unsigned long long will allow us to display only 378
    using lcd.print or Serial.print methods.

//((51539607540LL + 2969567055LL + 15925005LL + 34816LL + 169LL) / 144000000LL)
unsigned long long x1 = (51539607540 + 2969567055 + 15925005 + 34816 + 169)/144000000 ;
int *ptr;             //
ptr = (int*)&x1;
int m = *ptr;
lcd.print (m, DEC);   //LCD shows: 378
  1. To display the full result of Step-1, we need to use floating point data type (double which is
    64-bit (binary64) floating point type in DUE.
double x1 = (51539607540.0 + 2969567055.0 + 15925005.0 + 34816.0 + 169.0)/144000000.0 ;
lcd.print (x1, 13);   //LCD shows: 378.6467679513889
  1. The integer type result of the addition of 51539607540 and 2969567055 can't be displayed using print function as it supports only 32-bit data type. We may use the following codes to do it:
unsigned long long x1 = 51539607540 + 2969567055;//54509174595

for (int n = 0; n<=10; n++)
{
byte y1 = x1%10 + 0x30;
asciiArray[10-n] = y1;
x1 = x1/10;
}

for (int i = 0; i<=10; i++)
{
  lcd.write(asciiArray[i]);     //LCD shows: 54509174595
}

You can display 64-bit numbers this way with printf and Serial.print:

uint64_t bignum0 = 0xFFFFFFFFFFFFFFllu;
uint64_t bignum1 = pow(2, 64) - 1;
int64_t bignum2 = - pow(2, 62);
double bignum3 = -1.123456789876543;

void setup() {
  Serial.begin(250000);
}

void loop() {
  printf(" bignum0 = 0x%llx\n", bignum0);
  printf(" bignum0 = 0x%llX\n", bignum0);
  printf(" bignum1 = %llu\n", bignum1);
  printf(" bignum2 = %lld\n", bignum2);
  Serial.print(" bignum3 = ");
  Serial.println(bignum3,15);
  delay(1000);
}

what is printf() doing on the Due? IIRC, printf writes to stdout - what is stdout on the Due?

"By default, input is being given with the keyboard, and output is displayed on your screen. Your keyboard is your "standard input" (stdin) device, and the screen is the "standard output" (stdout) device." (Google)

I am impressed to see the clever way (Post#4) of displaying 64-bit integer data on the Serial Monitor of Arduino IDE using printf() function while Serial.print() is unable to do it.

Arduino DUE Board contains a very powerful 32-bit processor (SAM3X8E) which is comparable to Intel 80386DX processor.

The mechanism through which the Computer Monitor is a stdout device to an 80386DX-based Computer, it is same mechanism that makes the Serial Monitor of Arduino IDE a stdout device for the SAM3X8E-based Microcomputer (the Arduino DUE).

BTW @ard_newbie
printf(" bignum0 = 0x%llx\n", bignum0); // this statement works.

printf("Arduino"); //this statement does not work (does not show Arduino on Serial Monitor).

yes, surprisingly printf works now with 1.8.3 on my PC, with my older 1.6.12 on my notebook it didn't though.
So far I always used sprintf() plus Serial.print for that prupose.

printf("Arduino"); //this statement does not work (does not show Arduino on Serial Monitor).

i have to agree, that does not work - no idea why not

uint64_t bignum0 = 0xFFFFFFFFFFFFFFllu;
uint64_t bignum1 = pow(2, 64) - 1;
int64_t bignum2 = - pow(2, 62);
double bignum3 = -1.123456789876543;

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

void loop() {
  printf(" bignum0 = 0x%llx\n", bignum0);
  printf(" bignum0 = 0x%llX\n", bignum0);
  printf(" bignum1 = %llu\n", bignum1);
  printf(" bignum2 = %lld\n", bignum2);
  
  Serial.print(" (Serial.print) bignum3 = ");
  Serial.println(bignum3,15);

  printf("Arduino");  // does not show up!
  
  while(1);
}

ps,
perhaps Arduino printf() is not the ANSI C stdio.h printf but from either Arduino mimic lib.