Math and types

Where to find a good link for dealing with math. Everything I find doesn't give any good answers I'm looking for. They always start and finish with the same types. All the numbers I will be using will be whole numbers so in trying to save space in the processor I would like to know which sample would be best or if there's a better way of doing it. If there a good link covering this topic I would appreciate have it posted.

//--------sample 1---------------------
int First_Number = 4000;
long Second_Number = 52100;
double Product_Of_Numbers = 0;

Product_Of_Numbers = First_Number * Second_Number;

//--------sample 2----------------------

unsigned int First_Number = 4000;
unsigned int Second_Number = 52100;
double Product_Of_Numbers = 0;

Product_Of_Numbers = First_Number * Second_Number;

//---------sample 3-----------------------

unsigned int First_Number = 4000;
unsigned int Second_Number = 52100;
unsigned Product_Of_Numbers = 0;

Product_Of_Numbers = First_Number * Second_Number;

Most important to know is that the data type (outcome) of an (partial) expression is the largest data type of that expression.

So your sample 1 multiplies an int and a long GIVES a long as answer, and then that long is assigned to a double.

This behavior can cause the side effect of under- and overflow. To prevent this you must select a data type that is large enough to hold the MIN/MAX value.

ANother technique is casting which works (simplified) as follows

Sum_Of_Numbers = ((double)First_Number) * Second_Number;

The extra (double) instructs the compiler to convert that variable to a double before doing the math.

If you want to learn al the details a book about C/C++ is worth its money.


from your 3 samples above only the 1st will give the correct answer

A meaningful variable name would be nice:

Product_Of_Numbers = First_Number * Second_Number;

(picky-picky) Pete

el_supremo:
A meaningful variable name would be nice:

Product_Of_Numbers = First_Number * Second_Number;

(picky-picky) Pete

well, multiplication is just addition...

from your 3 samples above only the 1st will give the correct answer

I forgot to type in the type for the Product_Of_Numbers in the samples. It took me a while to figureout why only the first sample would work.

//--------sample 4----------------------

unsigned long First_Number = 4000;
unsigned long Second_Number = 52100;
unsigned long Product_Of_Numbers = 0;

Product_Of_Numbers = First_Number * Second_Number;

it is the overflow of the datatypes

it is the overflow of the datatypes

If I'm right, overflow of datatype only if the Sum_Of_Numbers is grater then 4,294,836,225

Sample 4 where I used unsigned long as the data type

First_Number fill never be greater then 65,535 Second_Number fill never be greater then 65,535 so the Sum_Of_Numbers will never grater then 4,294,836,225

a unsigned long Ranges from 0 to 4,294,967,295

Thanks for input. I confused myself even more now so I'll do some more digging if I can remember what I really wanted to learn.

@gletha

Can you manually figure out why Sample-2 would give incorrect result as pointed out by @robtillaart?

unsigned int First_Number = 4000;
unsigned int Second_Number = 52100;
double Product_Of_Numbers = 0;

Product_Of_Numbers = First_Number * Second_Number;


==> First_Number = 0x0FA0   (4000)
==> Second_Number = 0xCB84 (52100)

Product_Of_Number = 0x0A0 * 0XCB84 = 0xC6BEE80 (208400000)
==> The Compiler will keep only the low order 16-bit of the product : 0xEE80 (61056).

Serial.println(Product_Of_Numbers, 2); // shows: 61056.00 (incorrect)

To get correct result, do a cast as advised by @ robtillaart
Product_Of_Numbers = ((double)First_Number) * Second_Number;
Serial.println(Product_Of_Numbers, 2); //shows: 208400000.00 (correct)

I confused myself even more now

Even you have confused others more than you have confused yourself.

Your declaration:
double Product_Of_Numbers = 0;

says that you have declared a variable which will hold floating point number in binary64 format (supported by DUE); but, you have defined it by 0 rather than by 0.0.

GolamMostafa:
says that you have declared a variable which will hold floating point number in binary64 format (supported by DUE); but, you have defined it by 0 rather than by 0.0.

But, amazingly, the IEEE-754 floating point standard stores the value zero as all zeroes.
Cute, huh?

Should we follow the convention of the definition of a floating point number -- a number that has both integer and fractional part!

Zero doesn't have a fractional part, not even a really, really tiny one.

But Zero (0) is a real number -- when we go from + 3 to -3, we go through (across) it! If you ask me to present 27 in float form, I will present it as 27.00. Similarly, I will present 0 as 0.00!

GolamMostafa:
But Zero (0) is a real number -- when we go from + 3 to -3, we go through (across) it! If you ask me to present 27 in float form, I will present it as 27.00. Similarly, I will present 0 as 0.00!

The compiler is MORE than smart enough to know what when you set a float or double to 0, you mean 0.0. When you set it to 27, you mean 27.0. What else could it possibly assume? 0 should mean 0.0000001??? 0.5? Read up on HOW the compiler interprets literals, rather than making (incorrect) assumptions.
Regards,
Ray L.

Can you manually figure out why Sample-2 would give incorrect result as pointed out by @robtillaart?

No I can't. I wrote this program and get the same answer not matter what. I must be missing something like brains.

unsigned int First_Number = 4000;
unsigned long Second_Number = 52100;
double Product_Of_Number1 = 0;
double Product_Of_Number2 = 0;
double Product_Of_Number3 = 0;
void setup()
{

Serial.begin(9600);
}
void loop()
{
Product_Of_Number1 = First_Number * Second_Number;
Serial.print("1 - "); 
Serial.print(Product_Of_Number1); //shows: 1 - 208400000.00 
Serial.print('\n'); 
Product_Of_Number2 = ((double)First_Number) * Second_Number;
Serial.print("2 - "); 
Serial.print(Product_Of_Number2); //shows: 2 - 208400000.00
Serial.print('\n');  
Product_Of_Number3 = ((double)First_Number * Second_Number);
Serial.print("3 - "); 
Serial.print(Product_Of_Number3); //shows: 3 - 208400000.00
Serial.print('\n');  

}

AWOL:
Zero doesn't have a fractional part, not even a really, really tiny one.

Its fractional part has zero length so to say :slight_smile:

RayLivingston:
The compiler is MORE than smart enough to know what when you set a float or double to 0, you mean 0.0. When you set it to 27, you mean 27.0. What else could it possibly assume? 0 should mean 0.0000001??? 0.5? Read up on HOW the compiler interprets literals, rather than making (incorrect) assumptions.
Regards,
Ray L.

The IEE754 spec has a certain range of integer numbers it can represent exactly. If you use a float as an index in a for loop small deltas in the last significant digit can add up (or sub down or both) resulting in just an extra iteration or in one less. Similar type of problem occurs when you compare two floats for equality, although they might print the same value they are not necessary equal.

Can you manually figure out why Sample-2 would give incorrect result as pointed out by @robtillaart?

No I can't.

/--------sample 2----------------------

unsigned int First_Number = 4000;
  unsigned int Second_Number = 52100;
  double Product_Of_Numbers = 0;

Product_Of_Numbers = First_Number * Second_Number;

Since "first_number" and "second_number" are both of type "unsigned int", the calculation on the right side of the equals sign is also done in "unsigned int"-sized registers (16bits on AVR), this overflows and results in an incorrect answer BEFORE the code gets around to assigning the result to the "double."
You have to give the compiler instructions to change at least one of the values on the right to a big-enough type BEFORE doing the calculation:

Product_Of_Numbers = (unsigned long)First_Number * Second_Number;

at least one of the values on the right to a big-enough type BEFORE doing the calculation:

So that is why my reply #14 works. Thanks westfw for making it simple for me to understand.

What are you really trying to do that you care about this so much?
How much number-crunching do you intend to do?