Start Functions Events Constants Types Language Articles

Integer type

The integer type represents a number without decimals, as opposed to the float type which can have decimals.

Formally, the integer type is a 32-bit signed integer, which means that its range is from -2147483648 to 2147483647. Integer literals are specified just by entering the digits. They can optionally be preceded with a minus sign for negative numbers, but rigorously speaking, the sign is not part of the number, but an operator, and thus it takes code space. There are two exceptions: if the number is immediately after a type cast prefix, or if it is in the globals initialization, the sign will be part of the number and not take code space.

If an integer literal is out of the range of a 32-bit unsigned integer, the result will automatically be -1; otherwise, the result will be the value taken as a signed 32-bit integer. For example:

integer j = 12345678901234567890;

will set j to -1, but

integer j = 4294967294; // that's 2^32-2

will set j to -2.

Another way to specify an integer literal is in hexadecimal (also called base 16 or radix 16). The digits for hexadecimal are the normal digits from 0 to 9 plus the letters from A to F (case doesn't matter), making a total of 16 digits available (A is ten, B is eleven, and so on until F which is fifteen). In LSL, an hexadecimal number is entered by prefixing it with a zero and an ex; for example, 0x12abcd34 is an integer expressed in hexadecimal, equivalent to the decimal number 313249076. Since case doesn't matter, 0X12AbCd34 is the same number.

Unlike other languages which inspired the syntax of LSL, LSL does not support octal (base 8) literals.

Type casting an integer to/from other types

When a float is converted to an integer, the value is rounded towards zero, i.e. truncating the decimals. For example, (integer)-3.7 results in the integer -3, and (integer)3.7 results in the integer 3. If the float is too big to fit in an integer, the result is -2147483648. For example, (integer)1e30 gives the integer -2147483648. Note that that's different from the result of specifying a too big integer literal, which is -1.

For other rounding methods, see llFloor (round a float down towards negative infinity), llCeil (round up towards positive infinity), and llRound (round to closest integer).

Conversion of an integer to string results in the integer being converted to its decimal expression. For example, (string)-12345 results in the string "-12345", and (string)0x12ABCD34 results in the string "313249076".

Conversion of a string to an integer follows some special rules.

Type cast of an integer to/from vector, rotation, or key is not supported. Type cast of a list to integer is not supported either. Type cast of an integer to list results in a list containing that integer as the only element, just as when any other type is converted to list.

Examples

Examples of integer literals
Examples of type conversion between string and integer

Operations on integers

Integers can be added (+), subtracted (-), multiplied (*) and divided (/). When both sides of the operation are integer, the result is integer too. Note that this is true in the case of division in particular, which means that the operation is "integer division", returning the quotient (thus rounding towards zero). For example, the result of 7/2 is the integer 3, because 7 divided by 2 gives a quotient of 3. When either side of the operation is a float and the other an integer, the integer will be converted to float if it is not so already; for example, 3.0+2 is equivalent to 3.0+(float)2 and results in the float 5.0, and 7/(float)2 or (float)7/2 both result in the float 3.5. Note, however, that (float)(7/2) results in the float 3.0, because first 7/2 is performed, which results in 3, and then the conversion of 3 to float occurs.

Another operation available for integers (but not for floats) is called modulo, which means the remainder of the division. The symbol used for modulo is the percent sign %. For example, the result of 7%2 is 1 because the remainder of dividing 7 by 2 is 1; 51%15 gives 6 because when dividing 51 by 15, the remainder is 6.

A minus sign can prefix any integer value, and the result is the value with the sign changed. Note that it's much preferable to write -var than var*-1, as the former uses less code space and is faster.

Integers can be compared for equality (==), inequality (!=), less than (<), greater than (>), less or equal (<=) and greater or equal (>=). All of the comparison operators can be applied to two integers, resulting in either the integer TRUE (1) or the integer FALSE (0), depending on the result of the comparison. All of these operators can also be applied to float (if one of the arguments is an integer and the other is a float, the integer will be converted to float before comparing), but the result of the comparison is still an integer, either 0 or 1.

Logical and bitwise operators

Integers are also used as boolean values (values that express a truth value of either true or false, sometimes also called flags). See Boolean for details. There are three logical operations that operate on integers that are interpreted as boolean: the && ("logical and") operator, the || ("logical or") operator and the ! ("logical not") operator.

The logical and operator returns TRUE when both elements evaluate to a truth value of true (which means they are distinct from 0), and to FALSE otherwise.

The logical or operator returns FALSE when both elements are FALSE, and TRUE otherwise.

The logical not operator is a prefix that applies to a single operand. It returns TRUE if the operand is FALSE, and FALSE otherwise.

Examples of the boolean operators:

llOwnerSay((string)(2 && 3)); // displays 1 (the value of the constant TRUE)
llOwnerSay((string)(0 && 3)); // displays 0 (the value of the constant FALSE)
llOwnerSay((string)(2 && 0)); // displays 0
llOwnerSay((string)(0 && 0)); // displays 0
llOwnerSay((string)(2 || 3)); // displays 1
llOwnerSay((string)(0 || 3)); // displays 1
llOwnerSay((string)(2 || 0)); // displays 1
llOwnerSay((string)(0 || 0)); // displays 0
llOwnerSay((string)(! 3)); // displays 0
llOwnerSay((string)(! 0)); // displays 1

Finally, there are a series of operators called the bitwise operators. The name comes from the fact that they apply to the base-2 (also called binary) representation of the number, in which each digit is also called a bit.

The operators &, | and ^ stand for bitwise AND, bitwise OR and bitwise XOR respectively, and all perform their operation bit by bit of the corresponding numbers. For example, 5 in 32-bit binary is 00000000000000000000000000000101, and 3 is 00000000000000000000000000000011. Therefore, 5&3 equals 1, because:

So the final result is the binary number 00000000000000000000000000000001 which is 1 in decimal. Similarly, 5|3 is 7 (00000000000000000000000000000111 in binary). XOR results in 1 when the bits are different, and 0 when they are equal (or put another way, it flips only the bits of the first operand which are 1's in the second operand); therefore 5^3 is 6 (00000000000000000000000000000110 in binary).

The bitwise NOT operator is a unary operator (one that applies to single numbers, like the minus sign in front of a number does). It uses the symbol ~ (tilde) and results in each bit of the number being flipped. For example, ~5 returns the binary number 11111111111111111111111111111010 which equals the decimal number -6. In arithmetic terms, ~n performs the same operation as -1-n, because -1 is all ones in binary, and subtracting any binary number from it results in the bits of that number being flipped (e.g. in 4-bit arithmetic, 1111-1010 results in 0101).

The operator << takes two integers, and displaces the binary representation of the first number to the left by an amount of bits indicated by the second number, filling the digits inserted on the right with zeros, and making the higher-order bits to be lost. This effectively results in multiplying the first number by 2(second number). For example, 5<<3 returns 40, because 5<<3 inserts three zeros on the right and discards the ones on the left, resulting in the binary number 00000000000000000000000000101000 which is 40 in decimal; or in other words, it multiplies 5 by 2³, i.e. returns 5 times 8 which is 40.

The >> operator works similarly, but it displaces to the right, and instead of inserting zeros on the left, the leftmost bit (which is the sign bit as LSL uses twos complement arithmetic) is copied instead, as many times as necessary to fill the spaces. For example, the decimal number -8 is represented in 32-bit binary as 11111111111111111111111111111000; therefore -8>>1 results in the binary number 11111111111111111111111111111100 which equals -4.

The bitwise operators (especially the bitwise AND operator, &) are widely used in LSL, because many functions or events take or return integers whose binary expression represents a series of flags. For example, llGetAgentInfo returns an integer value in which the rightmost bit is 1 if the agent is flying, or 0 if not; the next bit is 1 if the agent has attachments, and 0 if not, and so on, for many bits of information. For that purpose, the constant AGENT_FLYING has the value 1 (all zeros and an 1, in binary), so that a bitwise AND of the result with that constant, gives either zero (meaning it's not set) or non-zero (meaning it's set); similarly, the constant AGENT_ATTACHMENTS has the value 2 (in binary, all zeros, a 1, and a 0), for which a bitwise AND will separate the corresponding bit of the returned value, and so on.

As another example, the parameter of the changed event is an integer indicating what has changed, and several bits can be set at the same time because several things can change at a time, therefore each of the CHANGED_xxx constants has one bit set according to the meaning of the bit (they are named in such a way that you only need to remember the name of the constant, not the bit position). And there are many more cases where integers are used as bit fields.

See also