Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Formatting a float to a string

Cheree Bury
ChereeMotion Owner
Join date: 6 Jun 2007
Posts: 666
06-29-2008 12:39
It seems like this should be available, but I can't seem to find it.

I need to convert a floating point number to a string. I want to set the number of decimal places, and trim the zeroes off of both sides. I would think this would have been written hundreds of times.

Does anyone have it? or am I gonna have to write it?
Osgeld Barmy
Registered User
Join date: 22 Mar 2005
Posts: 3,336
06-29-2008 14:32
(string) 1.258975648842135484310135454
Lee Ponzu
What Would Steve Do?
Join date: 28 Jun 2006
Posts: 1,770
06-29-2008 15:17
Another common trick is to pass the float thru an integer. So, if you want two decimal places you do something like

float x = 3.1415926
integer i = 100 * x; // i will be 314
x = 0.01 * i;

or

x = 0.01 * (integer)(100 * x);

You can truncate the string if you like, too.
_____________________
So many monkeys, so little Shakespeare.
Cheree Bury
ChereeMotion Owner
Join date: 6 Jun 2007
Posts: 666
06-30-2008 04:52
Thanks for your responses,

I guess I wasn't very clear about my request. What I was hoping for would be something like Visual Basic's Format function. Maybe not as elaborate, but somewhat similar.

Maybe I will start coding it; and hope that Mono shows up soon.
Very Keynes
LSL is a Virus
Join date: 6 May 2006
Posts: 484
07-01-2008 01:06
Mono should be up next month, but it wont help you as we will not have any access to it other than via LSL and it has been stated several times that there will be no language changes so as to ensure 100% compatability between scripts Compiled to MONO and scripts compiled to LSLRuntime. So go a head, create the function and post it in the Library, I am sure many others will make use of your work.
Haruki Watanabe
llSLCrash(void);
Join date: 28 Mar 2007
Posts: 434
07-01-2008 03:33
I didn't test this inworld, so it might need some changes (and, as usual, I'm sure that there's a more elegant solution)...

CODE


[Edit] Nice try - but it doesn't work... :( I'll elaborate a little more on this an repost the script later.

Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
07-01-2008 07:26
The easiest, least intensive solution is what Lee posted. There are no trim right/trim left functions.
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
Haruki Watanabe
llSLCrash(void);
Join date: 28 Mar 2007
Posts: 434
07-01-2008 07:37
I tried to make a function which formats a number with thousand-separators and free configurable decimal separator.

Would result in something like 4'123'456,735 (instead of 4123456.735)

Tried to do it with some typecasting instead of multiplication and found out that typecasting from a float to a string fails miserably.

Try this:

float test = 8.123456;
llOwnerSay("TEST: " + (string)test);

Will result in 8.123456

float test = 18.123456;
llOwnerSay("TEST: " + (string)test);

Will result in 18.123455

float test = 118.123456;
llOwnerSay("TEST: " + (string)test);

Will result in 118.123459

LSL sucks...
Cheree Bury
ChereeMotion Owner
Join date: 6 Jun 2007
Posts: 666
07-02-2008 05:40
From: Lee Ponzu
Another common trick is to pass the float thru an integer. So, if you want two decimal places you do something like

float x = 3.1415926
integer i = 100 * x; // i will be 314
x = 0.01 * i;

or

x = 0.01 * (integer)(100 * x);

You can truncate the string if you like, too.


This is a common way of truncating the numbers, but it doesn't finish the job.

When I use this procedure, my resulting string = 3.1400000 when I want it to be 3.14

And when the number is 3.0000000, I want it to output 3.0 (I do not want to truncate that final 0.)

So I will work on it (and pass the resulting code here when I have it.)

Thanks
Domino Marama
Domino Designs
Join date: 22 Sep 2006
Posts: 1,126
07-02-2008 06:26
string formatFloat( float num, integer places )
{
float f = llPow( 10.0, places );
integer i = llRound(num * f);
return (string)((integer)(i / f)) + "." + llGetSubString((string)i , -places, -1);
}

you could set a string to the return value and check for trailing 0s if you don't like the fixed format.

Edit: Forgot to mention. This way fails for values between -0.099999 and 0.0999999, for my use this wasn't an issue. it's an easy patch if you need the full range:

string formatFloat( float num, integer places )
{
float f = llPow( 10.0, places );
integer i = llRound(num * f);
string s = "00000" + (string)i; // number of 0s is max places value - 1
return (string)((integer)(i / f)) + "." + llGetSubString( s, -places, -1);
}
Dora Gustafson
Registered User
Join date: 13 Mar 2007
Posts: 779
07-02-2008 06:36
From: Haruki Watanabe
LSL sucks...

aha...
One of the conditions in LSL are 32bit floats, 8 for the exponent and 24 for the mantissa. One bit is for the sign so 23 bits are left for digits: 11111111111111111111111binary equals 8388607decimal. That is 7 decimal digits! More decimal digits can arise from the binary to decimal conversion but give no sense.
_____________________
From Studio Dora
Deanna Trollop
BZ Enterprises
Join date: 30 Jan 2006
Posts: 671
07-02-2008 09:29
From: Dora Gustafson
One bit is for the sign so 23 bits are left for digits
But the mantissa is assumed to be preceded by a 1 in all cases except when the exponent field is -127. (Note, that's a binary exponent, 2^n, not a decimal exponent). So for the vast majority of applications, the mant is effectively 24 bits.

But as you yourself pointed out in another thread, extremely large negative exponent values are possible (specifically, binary -126), so the smallest decimal value expressible by a 32-bit float is approx ±1.4e-45, which would take many more than 6 decimal places to represent.
Ordinal Malaprop
really very ordinary
Join date: 9 Sep 2005
Posts: 4,607
07-02-2008 09:37
An automatically truncating float to string function, looking backwards from the last digit:

CODE

string float2string(float f)
{
string s = (string)f;
string digit = "";
do {
if (digit == "0") s = llGetSubString(s, 0, -2);
digit = llGetSubString(s, -1, -1);
} while (digit == "0");
if (digit == ".") s = s + "0";
return s;
}
_____________________
http://ordinalmalaprop.com/forum/ - visit Ordinal's Scripting Colloquium for scripting discussion with actual working BBCode!

http://ordinalmalaprop.com/engine/ - An Engine Fit For My Proceeding, my Aethernet Journal

http://www.flickr.com/groups/slgriefbuild/ - Second Life Griefbuild Digest, pictures of horrible ad griefing and land spam, and the naming of names
Cheree Bury
ChereeMotion Owner
Join date: 6 Jun 2007
Posts: 666
07-05-2008 08:56
From: Domino Marama
string formatFloat( float num, integer places )
{
float f = llPow( 10.0, places );
integer i = llRound(num * f);
return (string)((integer)(i / f)) + "." + llGetSubString((string)i , -places, -1);
}

you could set a string to the return value and check for trailing 0s if you don't like the fixed format.

Edit: Forgot to mention. This way fails for values between -0.099999 and 0.0999999, for my use this wasn't an issue. it's an easy patch if you need the full range:

string formatFloat( float num, integer places )
{
float f = llPow( 10.0, places );
integer i = llRound(num * f);
string s = "00000" + (string)i; // number of 0s is max places value - 1
return (string)((integer)(i / f)) + "." + llGetSubString( s, -places, -1);
}


I was just working on this problem. Thanks for the update.

Now, the final problem: negative numbers don't work. -0.033699 comes out as 0.-34 (with places=3)



Update:

I have modified your code to allow for negatives:

string formatFloat( float num, integer places )
{
string negSign = "";
if (num < 0.0) negSign = "-";

float f = llPow( 10.0, places );
integer i = llRound(llFabs(num) * f);
string s = "00000" + (string)i; // number of 0s is max places value - 1
return negSign + (string)((integer)(i / f)) + "." + llGetSubString( s, -places, -1);
}