Float
A float is an IEEE-754 32-bit floating point value ranging from ±1.401298464E-45 to ±3.402823466E+38.
Examples:
9.9 10.0 100000.1
LSL floats can be specified in scientific notation, e.g. 1.123E-2 or 512E+3.
Additionally, the letter f or F can be appended. This is a relic from C, where the f is needed to specify for the compiler that it is a float and not a double (LSL only uses floats).
A 32-bit float is divided into a 24-bit signed “mantissa” (containing the actual significant digits) and an 8-bit signed “exponent” (representing the magnitude that the mantissa will be multiplied with). A 23-bit (1 bit lost for sign) mantissa gives a precision equivalent to approximately 7 decimal digits (more exactly log10(223)). This means values are rarely exactly stored and, often more disturbingly, addition or subtraction of two numbers of vastly different magnitudes might yield unexpected results, as the mantissa can’t hold all the significant digits.
As per IEEE-754, LSL supports negative zero, there is currently no way of detecting negative zero, except by typecasting to a string .
Example:
340000000.0 + 4.0 = 340000000.0
The correct answer (340000004.0) has 9 significant digits, thus the last two digits are lost.
Some functions have tooltips within the LSL editor that say “F32”, indicating a 32-bit float, rather than simply “float”. However, all floats in LSL are 32-bit. So if it says “F32”, it may be read as just “float”.
Certain things are picky about whether they are passed a float or an integer. -To make an integer into a float, add .0 to the end. Other functions don’t require this, and so the joys of non-uniform functions can be experienced. However, it is necessary to explicitly cast a float to an integer, since precision is lost.
There are 4 techniques for converting a float to an integer.
Function Name | Purpose |
(integer) | Returns the integer portion of the float, ignoring the decimal. |
llRound | Rounds float around 1/2 (1.2 rounds to 1, 1.6 rounds to 2, -2.5 rounds to -3). |
llCeil | Rounds float up to an integer, partially equivelent to typecast. |
llFloor | Rounds down to an integer, partially equivelent to typecast. |
Note: using the typecast equivalent, if available, is going to be faster and use less memory.
Note Details: If speed is a concern (integer) should always be used.
Typecasting uses slightly less memory(10-20b)
Function Name | Slower | Sign | Code |
llFloor | 50% | + | (integer)float |
llRound | 30% | – | (integer)(float – 0.5) |
llRound | 30% | + | (integer)(float + 0.5) |
llCeil | 50% | – | (integer)float |
If you wish to typecast a float to a string whilst omitting the trailing zeroes (and dot if it is actually an integer value), this code may help you:
string float2string(float input) { string result=(string)input; integer i=llStringLength(result); while(llGetSubString(result,--i,i)=="0"); result = llDeleteSubString(result,i+1,llStringLength(result)); integer dot = llStringLength(result)-1; if(llGetSubString(result,dot,dot) == ".") result = llDeleteSubString(result,dot,dot); return result; }
For the interested reader, there is a good article about the floating standard:
What Every Computer Scientist Should Know About Floating-Point Arithmetic
This article explains the concepts behind floating point arithmetic, and often answers questions before they are asked.