Unsigned long proper calculation method

I am trying to put the result of a calculation that uses an int and an uint8_t and for testing purposes lets include a float aswell.
Do i need to convert every parameter of the calculation to and unsigned long using the (unsigned long) datatype prefix inside the calculation to have a proper and usable as unsigned long result?

for example:

int a = 3054;
uint8_t b = 6;
float c = 1.15;

unsigned long Result = (a/b)*c;

I'm pretty sure this is gonna do al sorts of wacky things so my question is how to properly do this?
What works and what is the best approach to this?

unsigned long Result = (unsigned long) ((a/b)*c);
or must i convert every single non unsigned long into an UL seperatly?:
unsigned long Result = ( (unsigned long) a / (unsigned long)b) * (unsigned long) c);
offcourse this way the float vallue will completely change the result here, a better way i believe should be to convert the result of the calculation to have the best accuracy?

No. The compiler promotes every variable in the calculation so that the calculation is done in the "highest" form, but the rules are a bit complicated. Look up something like "C/C++ type promotion".

If one variable is declared unsigned long, shorter integers will also be treated as unsigned long. A float supersedes unsigned long.

Ok so

unsigned long Result;
unsigned long Result = (a/b)*c;

and

unsigned long Result;
Result = ( unsigned long) a /b)*c;

and

unsigned long Result;
Result = (unsigned long) ((a /b)*c);

are all perfectly viable options?
I am going to use the Result in a comparison check using micros();
I've read somewhere that usually you have to put UL at the end of the value when using unsigned long, but i assume that is done automaticly after the calculation?

Viable, but the results may be very different. Note that the middle expression is missing a parenthesis and won't compile without errors.

In the last expression, the compiler decides how to promote the variables, and makes the result unsigned long. Study the rules!

The (unsigned long) on the left side of the "=" has nothing to do with what happens on the right side of the "=".

i assume that is done automaticly after the calculation?

No. UL is used to identify the type of a naked number.

1UL equals 1 but is treated as unsigned long.
"1" is treated as the default integer type, which varies from one compiler to another.

hmm, so in my calculation i would only need to place the UL tag right after the last number incase i use digits in the equation? doing this once will ultimately convert the final result into an UL?
would that be the same as having
unsigned long Result = (unsigned long) ((a /b)*c);
and
unsigned long Result = (a /6UL)*c;
and what happens when i put the UL tag in a float 1.15UL would that convert it to 1 or to 115?

No, it is not going to do ANY "wacky things". It will follow the very precise and detailed rules specified for c++ expression evaluation and type conversion. You would be wise to study and LEARN those rules rather than trying things blindly until you get the result you want.

3 Likes

If i would be asked to add the numbers --

a = 3065
b = 6
c = 1.15

I would be doing the following:

  a = 3065.00
+ b =    6.00
+ c =    1.15
-------------------
sum = 3072.15

And accordingly, I woud write the following codes for my Arduino UNO Computer:

float sum = (float)a + (float)b + c;
Serial.println(sum, 2);  //shows: 3072.15

UL stands for unsigned long int, and it is used for a variable that wil hold number with no frcational part; but. 1.15 is a number that has a fractional part; so, 1.15UL is illegal?

1 Like

You can easily mess up. Order is important, as is your ().
Consider:

void setup() {
  Serial.begin(115200);
  int a = 3053;  //changed between runs
  uint8_t b = 6;
  float c = 1.15;
  unsigned long Result;
  float Result2;
Serial.println("-----------------");
Serial.print("a,b,c ");
Serial.print(a);
Serial.print("  ");
Serial.print(b);
Serial.print("  ");
Serial.println(c);

//with an int output
  Result = (a / b) * c;
  Serial.println(Result);
  Result = a / b * c;
//...different order
  Serial.println(Result);
  Result = c * a / b;
  Serial.println(Result);
  Result = c * (a / b);
//with a float output  
  Serial.println(Result);
  Result2 =  (a / b) * c;
  Serial.println(Result2);
  Result2 =  a / b * c;
//...different order
  Serial.println(Result2);
  Result2 = c * a / b;
  Serial.println(Result2);
  Result2 = c * (a / b);
  Serial.println(Result2);
}
void loop() {}

And the output:

 -----------------
 a,b,c 3053  6  1.15
 584
 584
 585
 584
 584.20
 584.20
 585.16
 584.20
 -----------------
 a,b,c 3054  6  1.15
 585
 585
 585
 585
 585.35
 585.35
 585.35
 585.35
 -----------------
 a,b,c 3055  6  1.15
 585
 585
 585
 585
 585.35
 585.35
 585.54
 585.35
1 Like

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