Unofficial LSL Reference

[[types:integer]]


Unofficial LSL reference

User Tools

Login

You are currently not logged in! Enter your authentication credentials below to log in. You need to have cookies enabled to log in.

Login

Forgotten your password? Get a new one: Set new password

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.

  • If the string starts with "0x" or "0X", the integer will be taken as hexadecimal, but not if it starts with "-0x" or "-0X".
    • After the "0x" or "0X", a sequence of digits from 0 to 9 and letters from A to F, in either upper or lower case, will be taken as the hexadecimal number.
    • Any remaining characters after the last valid hexadecimal digit will be ignored.
    • If there are no valid hexadecimal characters after the "0x" or "0X", the result will be zero.
    • If the hexadecimal number is too big to fit an integer, the result will be -1.
  • Otherwise, it will be taken as decimal. A decimal number consists of:
    • Any number of spaces (or other spacing characters, namely tabs, line feeds, vertical tabs, form feeds, or carriage returns).
    • One optional sign, either plus or minus.
    • One or more decimal digits.
    • Any remaining characters after the last valid decimal digit will be ignored.
    • If the decimal number is not valid (does not follow the above rules), the result will be zero.
    • If the decimal number is too big to fit an integer, the result will be -1.

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
  • 342 is a literal representing the integer 342.
  • 0x1 is a literal representing the integer 1.
  • 0XA is a literal representing the integer 10.
  • 3. is not an integer literal; it is a float literal.
Examples of type conversion between string and integer
  • (string)0xA gives the string "10".
  • (integer)"\n +123abc" gives the integer 123. Note that \n is the line feed character (popularly known as newline).
  • (integer)" + 123abc" gives the integer 0, because there's a space after the sign.
  • (integer)" ++123abc" gives the integer 0, because there's more than one sign.
  • (integer)"stuff123" gives the integer 0, because there's no digit at the beginning.
  • (integer)"-123" gives the integer -123.
  • (integer)"0123" gives the integer 123. Again, octal is not supported here either.
  • (integer)"-0x3" gives the integer 0. Since it does not start with "0x" but with a minus sign, it follows decimal rules.
  • (integer)"0x3" gives the integer 3.
  • (integer)"0x2astuff" gives the integer 42 (0x2A in hexadecimal).
  • (integer)"0xcafeteria" gives the integer 51966 (0xCAFE in hexadecimal). c, a, f and e are valid hexadecimal digits, but t is not, so the parsing finishes there.

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:

  • for the first bits, 0 AND 0 is 0;
  • for the second bits, 0 AND 0 is 0;
  • ...
  • for the thirtieth bits, 1 AND 0 is 0;
  • for the thirty-first bits, 0 AND 1 is 0;
  • for the thirty-second bits, 1 AND 1 is 1.

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