Floats getting inaccurate very quickly
|
|
Ochi Wolfe
Furdamentalist
Join date: 18 Dec 2004
Posts: 25
|
03-16-2007 09:00
Hello everyone. I just experienced something odd with a simple script that I wrote to test something. The only thing I do is to add 0.2 to a global float in a timer and display the value. I noticed the value gets very inaccurate very quickly. Now I wonder if this is the way it's meant to work or if this is a bug with the script being compiled with the First Look and/or Linux version. I'm using First Look build 59036 on Linux. Put this script in a box and observe: From: someone float floatCounter;
default { state_entry() { llSetTimerEvent( 0.1 ); }
timer() { llSetText( (string)floatCounter, <1,1,1>, 1 ); floatCounter += 0.2; } }
|
|
Lee Ponzu
What Would Steve Do?
Join date: 28 Jun 2006
Posts: 1,770
|
03-16-2007 09:56
As an experiment, compute the value two ways and compare...
integer i=0; timer() { llSetText( (string)floatCounter, <1,1,1>, 1 ); floatCounter += 0.2; fC = i*0.2; i++; // compare floatCounter and fC. }
...or some such. 0.2 cannot be represented perfectly in binary floating point, so every time you add that, you are adding a little non-random noise as well. It adds up quickly. This is a well known problem in most languages. A common solution is to use integers, scaled accordingly, and translate to human readable numbers only on demand.
|
|
Ralph Doctorow
Registered User
Join date: 16 Oct 2005
Posts: 560
|
03-16-2007 10:09
LSL's use of float rather than double doesn't help either
|
|
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
|
03-16-2007 16:08
Bring back BScaling 
|
|
Winter Ventura
Eclectic Randomness
Join date: 18 Jul 2006
Posts: 2,579
|
03-16-2007 16:20
Personally.. how about actual math with actual numbers?
you know.. where 1.00 - 0.25 = 0.75, not 0.749 (and don't EVEN get me started on .125, .375, .625, and .875... GRRRR)
Did Linden Labs get a bulk discount for buying old Pentium chips or something?
_____________________
 ● Inworld Store: http://slurl.eclectic-randomness.com ● Website: http://www.eclectic-randomness.com ● Twitter: @WinterVentura
|
|
Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
|
03-17-2007 08:51
From: Winter Ventura Personally.. how about actual math with actual numbers?
you know.. where 1.00 - 0.25 = 0.75, not 0.749 (and don't EVEN get me started on .125, .375, .625, and .875... GRRRR)
Did Linden Labs get a bulk discount for buying old Pentium chips or something? This is a completely unfair complaint. Every modern CPU in every modern personal computer will have these inaccuracies. It's just how floating point computation on computers works! It's just not feasible to do "real math with actual numbers" as you put it. Or rather, it is, but they do it with binary numbers rather than decimal, and you lose some in the conversion. 0.2 is quite likely to be represented as a repeating binary floating point number, since that's the most exact binary representation you can get. That said, 0.125, 0.375, 0.625, 0.25, and 0.75 (for example) SHOULD represent precisely. Did you actually take your example equation from a script you'd tried in SL?
|
|
Brain Curry
Registered User
Join date: 15 Jun 2006
Posts: 9
|
03-17-2007 11:17
From: Lex Neva This is a completely unfair complaint. Every modern CPU in every modern personal computer will have these inaccuracies. It's just how floating point computation on computers works! It's just not feasible to do "real math with actual numbers" as you put it. Or rather, it is, but they do it with binary numbers rather than decimal, and you lose some in the conversion. 0.2 is quite likely to be represented as a repeating binary floating point number, since that's the most exact binary representation you can get.
That said, 0.125, 0.375, 0.625, 0.25, and 0.75 (for example) SHOULD represent precisely. Did you actually take your example equation from a script you'd tried in SL? *koff* CL-USER> (let ((x 0)) (dotimes (i 10000) (setf x (+ x 0.2))) x) 1999.8058 CL-USER> (let ((x 0)) (dotimes (i 10000) (setf x (+ x (/ 2 10)))) x) 2000
|
|
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
|
03-18-2007 06:08
From: Brain Curry *koff* CL-USER> (let ((x 0)) (dotimes (i 10000) (setf x (+ x 0.2))) x) 1999.8058 CL-USER> (let ((x 0)) (dotimes (i 10000) (setf x (+ x (/ 2 10)))) x) 2000
That would be Lisp being smart. The result would be dependent upon the platform and Lisp implementation. (congrats on mentioning an RPN language).
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river. - Cyril Connolly
Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence. - James Nachtwey
|
|
Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
|
03-18-2007 08:41
What does it do, keep around a numerator and denominator and do divisions analytically?
I stand by what I said earlier: it's not feasible to do this kind of thing in a system like SL.
Incidentally, Lisp is Polish, not Reverse Polish. In RPN, the operator follows the operands.
|