wrote this ages ago, it isn't very fast but it is accurate.
Works flawlessly and LSL can parse directly to floats again without any special code

just use a (float) typecast.
Discussion thread: /54/fb/84483/1.html
Changes:
Rewrote the code almost from scratch, imported much of the knowledge learned from Float2Hex and float-union-integer (shares some code with FUI). Optimized the code, added comments, and descriptive variable names. Fixed a crashing bug and added precision to the math (won't effect the output). Relaxed some of the string method to be faster. Basically, everything has changed. It should also be *faster*. Cleaner logic.
CODE
string Float2Sci(float input)
{
if(input == 0.0)//handles negitive zero
return llDeleteSubString((string)input, -5, -1);//trim off the trailing zero's, don't need them.
float frac = llFabs(input);//we put the negitive back at the end.
string mantissa = (string)frac;//this may be a string of about 47 characters long.
integer exponent = -6;//default exponent for optical method
if(frac < 16.0)//optical might fail
if(frac != (float)mantissa)//optical did fail
jump in;
//optical will work, so all we need do is remove the decimal point and jump to optical.
mantissa = llDeleteSubString(mantissa, -7, -7);
jump optical;
@in;
//Ugly Math version; ugly in the sence that it is slow and not as elegant as working with it as a string.
//A) calculate the exponent via approximation of C log2()
//B) use cludge to avert fatal error in approximation of log2 result (only a problem with values >= 0x1.FFFFF8p127)
// the exponent is sometimes reported as 128, which will bork float math, so we subtract the test for 128.
// max_float btw is 0x1.FFFFFEp127, so we are only talking a very small number of numbers.
//C) normalize the float with questionable exponent
//D) calculate rounding error left from log2 approimation and add to normalization value.
// the '|' acts like a '+' in this instance but saves us one byte.
integer position = (24 | (3 <= frac)) - (integer)( //D
frac /= (float)("0x1p"+(string)( //C
exponent = (exponent - (( //B
exponent = llFloor(llLog(frac) / 0.69314718055994530941723212145818) //A
) == 128))
))
);
//this pushes the float into the interger buffer exactly.
//since the shift is within integer range, we don't need to make a float.
integer int = (integer)(frac * (1 << position));
integer target = (integer)(frac = 0.0);//since the float is in the integer buffer, we need to clear the float buffer.
//we don't use a traditional while loop, and instead opt for a do-while, because it's faster
//since we may have to do about 128 iteration, this savings is important,
//the exponent needs one final adjustment because of the shift, we do it here to save memory & it's fasfter.
//The two loops try to make exponent == position by shifting and multiplying.
//when they are equal, then this should be true ((int * llPow(10, exponent)) == llFabs(input))
//That is of course assuming that the llPow(10, exponenet) result has enough percision.
//We recycle position for these loops as a temporary buffer. This is so we can save a few operations.
//If we didn't, then we could actualy optimize the variable out of the code; though it would be slower.
if(target > (exponent -= position))
{//apply the rest of the bit shift if |input| < 1
do
{
if(int < 0x19999999)//(0x80000000 / 5)
{//won't overflow, multiply in 5
int = int * 5 + (position = (integer)(frac *= 5.0));
frac -= (float)position;
target = ~-target;
}
else
{//overflow predicted, devide by 2
frac = (frac + (int & 1))/2;
int = int >> 1;
exponent = -~exponent;
}
}while(target ^ exponent);
}
else if(target ^ exponent)//target < exponent
{//apply the rest of the bit shift if |input| > 1
do
{
if(int < 0x40000000) //(0x80000000 / 2)
{//won't overflow, multiply in 2
int = (int << 1) + (position = (integer)(frac *= 2.0));
frac -= (float)position;
exponent = ~-exponent;
}
else
{//overflow predicted, devide by 5
frac = (frac + int%5) / 5.0;
int /= 5;
target = -~target;
}
}while(target ^ exponent);
}
//int is now properly calculated, it holds enough data to accurately describe the input in conjunction with exponent.
//we feed this through optical to clean up the answer.
mantissa = (string)int;
@optical;
//it's not an issue that we may be jumping over the initialization of some of the variables,
//we initialize everything we use here.
//to accurately describe a float you only need 9 decimal places; so we throw the extra's away
if(9 < (target = position = llStringLength(mantissa)))
position = 9;
//chop off the tailing zero's; we don't need them.
do; while(llGetSubString(mantissa, position, position) == "0" && (position = ~-position));//faster then a while loop
//we do a bad thing, we recycle 'target' here, position is one less then target,
//"target + ~position" is the same as "target - (position + 1)" saves 6 bytes.
//this block of code actualy does the cutting.
if(target + ~position) mantissa = llGetSubString(mantissa, 0, position);
//insert the decimal point (not strictly needed). We add the extra zero for asthetics.
//by adding in the decimal point, it simplifies some of the code.
mantissa = llInsertString(mantissa, 1, llGetSubString(".0", 0, !position));
//adjust exponent from having added the decimal place
if((exponent += ~-target))
mantissa += "e" + (string)exponent;
//return with the correct sign.
if(input < 0)
return "-" + mantissa;
return mantissa;
}
Old Version:
CODE
float LOG2 = 0.30102999566398119521373889472449;
string FloatToSci(float Feed)
{
integer c;
integer d;
integer e;
float AFeed = llFabs(Feed);
integer Exp;
string Mant = (string)AFeed;
if(AFeed<16.0) //unsure about optical
{
if(AFeed!=(float)Mant) //optical fails
{
//55 bits used.
//d is the bitshift
//AFeed is the
integer f;
float tff;
c=(integer)((AFeed / llPow(2,d = llFloor(llLog10(AFeed) / LOG2))) * llPow(2,24));
d -= 24;
//time to apply the rest of the bit shift AFeed<1
while(e>d)
{
//overflow test
if(c >= 0x19999999) //(0x80000000 / 5)
{//overflow predicted, devide by 2
tff = (tff + c%2)/2;
c/=2;
++d;
}
else
{//won't overflow, multiply in 5
c = c*5 + (f = (integer)(tff*=5.0));
tff -= (float)f;
--e;
}
}
//time to apply the rest of the bit shift AFeed>1
while(e<d)
{
if(c >= 0x40000000) //(0x80000000 / 2)
{//overflow predicted, devide by 5
tff = (tff + c%5) / 5.0;
c /= 5;
++e;
}
else
{//won't overflow, multiply in 2
c= c * 2 + (f = (integer)(tff *= 2.0));
tff -= (float)f;
--d;
}
}
Mant = (string)c;
Exp = d;
//use this to speed things up, but output will be ugly and possibly wasteful.
// jump quick;
d = llStringLength(Mant);
jump go;
}
}
d = llStringLength(Mant);
if((c = llSubStringIndex(Mant,"."))+1)
{//remove the decimal, this makes everything else easier.
Exp -= (d -= 1) - c;
Mant = llDeleteSubString(Mant,c,c);
}
@go;
if(d>9 || llGetSubString(Mant,-1,-1)=="0")
{
if((e = d)>9)
c = 9;
else
c = d - 2;//already checked the last digit.
while(llGetSubString(Mant,c,c)=="0" && c)
--c;
Exp += e - (d = (c + 1)) + (c!=-1)*c;
Mant = llInsertString(llDeleteSubString(Mant, c+1, e), 1, llGetSubString("0.0", d>0, 1 + (d<2)));
}
else
{
if(d)
Exp += d - 1;
Mant = llInsertString(Mant, 1, llGetSubString("0.0", d>0, 1 + (d<2)));
}
@quick;
if(Exp)
{
if(Exp>0)
Mant += "E+" + (string)Exp;
else
Mant += "E" + (string)Exp;
}
if(Feed<0)
return "-" + Mant;
return Mant;
}