In the line below Iwahat is the significance of the L as the line does not work without the L
long OFF_Time1 = ((1000L * 60L * 2));
The L forces the calculation to be done as long integer. Without it, on some Arduinos, 16 bit integers are assumed and the multiplication overflows.
1. Without L (for long (32-bit) data type), the expected computed result is:
==> 120000 decimal (positive number)
==> 1D4C0 in hex
==> 1 1101 0100 1100 0000 in binary
2. As Arduino UNO uses 16-bit (int type) processing buffer during computation, it will save only 1101 0100 1100 0000 (the lower 16-bit ). After that this value will be copied/transferred into 32-bit destination variable named OFF_Time1.
3. Because, OFF_Time1 is a 32-bit varaible; but, it has received only 16-bit; so, the MSBit (1) of the received 16-bit data is copied into all positions of upper 16-bit of OFF_Time1 variable (this is how the compiler works!). Now, the OFF_Time1 variable contains:
1111 1111 1111 1111 1101 0100 1100 0000.
4. Now, because the data type of OFF_Time1 is int, the following print() command will look into MSBit of the content of OFF_Time1 varaiable. If it is 1 (HIGH), the data will be considered in 2's complement form. Accordingly, the display will show:
==> 1111 1111 1111 1111 1101 0100 1100 0000.
==> -1 x 231 + 0x7FFFD4C0
==> -2147483648 + 2147472576
==> -11072
void setup()
{
Serial.begin(9600);
long OFF_Time1 = 1000 * 60 * 2;
Serial.println(OFF_Time1); //shows: -11072
}
void loop(){}
5. There is a problem in getting the expected positive result which is solved by telling the compiler to use 32-bit processing buffer instead of default 16-bit buffer, and it is done by appending L with the data items.
6. Now, the multiplication result is
0000 0000 0000 0001 1101 0100 1100 0000 (32-bit) which is copied/transferred into destination variable OFF_Time1 and NOT 1 1101 0100 1100 0000 is copied.
7. Now, the print() command looks at the MSBit of the content of OFF_Time1 and finds that the bit is 0; as a result, the value appears as positive:
==> 0000 0000 0000 0001 1101 0100 1100 0000
==> 0001D4C0 in hex
==> 120000 in decmal
void setup()
{
Serial.begin(9600);
long OFF_Time1 = 1000L* 60L * 2;
Serial.println(OFF_Time1); //shows: 120000
}
void loop(){}
Quiz: Will the problem be solved by declaring the destination variable as unsigned long OFF_Time1; and without appending L with the data items? What value will appear on the Serial Monitor following Serial.print() command?
Thanks guys for the answers. I thought specifying long would take care of large numbers. Why do I not need to add the L to all parts of OFF time/
The formula on the right of the '=' sign is evaluated at compile time. By default, the compiler for 8-bit AVR processors will do that using 16-bit math. The "L" tells it to do the entire computation using 32-bit math. That's true regardless of the data type of the variable that is being initialized by the statement.
So, without the "L", the complier would compute the right hand side using 16-bit math and use the result to initialize your 32-bit variable 'OFF_Time1'.
PS -- For millis() type timing, you should be using "unsigned long" rather than "long". So:
unsigned long OFF_Time1 = ((1000UL * 60UL * 2));
Note that this
[code]
OFF_Time3 = 1000 * 60 * 2L;
Serial.println(OFF_Time);
[/code]
still creates an integer overflow, because the compiler works strictly left to right. By the time it gets to the "2L" you already have an overflow. So, place your "L" along with first number in the expression or with all of them.
The same will happen with variables declared as int
. You can force long arithmetic by casting them to long
or having a long constant or variable at the beginning of the expression . Try this:
void setup()
{
int a=10000;
int b=10000;
Serial.begin(115200);
Serial.println(a * b);
Serial.println((long)a * b);
Serial.println(1L * a * b);
Serial.println(a * b * 1L);
}
void loop(){}
Now I understans THANKS
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.