RE: BUG! Erratic for loop behavior

new topic     » goto parent     » topic index » view thread      » older message » newer message

Hi!

My 2P on the subject.

I wrote this little program (see under) to help visualize the floating point
(im-)precision in Eu floating point arithmetic.
Basically it just outputs the results of some simple calculations with a lot of
decimal positions but with 0's replaced by another char to improve readibility.
>From this you can see that there is fluctuating relative error on the order of
>10e-15 to 10e-16, sometimes positive, sometimes negative. By relative I mean the
>ratio of the error to the magnitude of the number represented. IOW if you make
>calculations with numbers on the order of 1 (say 1.5423/2.9997) you would expect
>an absolute error on the order of 1e-15 or 0.000000000000001, and with numbers in
>the millions the absolute error would be on the order of 1e-9 or 0.000000001
>(please count the 0's for me, i'm not sure).

My question to the specialists out there: is it what one would expect given that
it is claimed that Euphoria uses internally the 64-bit (double precision) IEEE
floating point arithmetic?

A challenge for the brave: write a program to see if the errors cancel out on
the average or if there is a risk of cumulative errors, i.e. that the 1e-15
_relative_ precision becomes, say 1e-9, if you compute the sum of a million
numbers.

Now let's come back to the original message from Andy. As shocking as it seems
at first sight this is completely normal. Don't forget that a for-loop contains
implicitely a check for equality (if <var>=<end value>) on each cycle. Now even
if Euphoria (or any other language) used 65536-bit precision floating point
arithmetic you would still be at risk. The exact number of executions of the loop
would still be uncertain. Why? Because the equality test is ultimately performed
by the hardware in a strictly bit-for-bit way.  And as we have seen there is
always a chance that the internal representations of the current value of <var>
and of <end value> will differ in at least one bit and it does not matter if it
is the 65536-th one, the test will fail and you will get one cycle too much (or
too few).

The morale is: either use only integer values in for-loops or replace the
for-loop with a while-loop.

In the former case you would write:
"for i = 311 to 342 by 1" and use i/10 inside the loop or equivalently "for i =1
to 32" and use (i+310)/10
In the latter case the while loop would read:
i=31.1
while i < 34.3 do
   i += .1
end while

Henri Goffin

-------< start >--------
include get.e
atom a

function replace_in_string(sequence s, object o, object n)
sequence so

if atom(o) then
	so = repeat(o, length(s))
	s += (s = so) * (n - o)
	return s
else
	for i = 1 to length(o) do
		s = replace_in_string(s, o[i], n[i])
	end for
	return s
end if
end function

procedure Xprintf(atom nr, atom fl)
sequence xp
integer ix

xp = sprintf("%d\t%30.25f\n",{nr, fl})
ix = match(".", xp)
xp[ix+1..length(xp)] = replace_in_string(xp[ix+1..length(xp)], '0', '-')
puts(1,xp)
end procedure

for k = 1 to 100 do
	system("cls",2)
	printf(1,"\n\nk = %d\n",{k})
	a = 0
	for i = 1 to 40 do
		Xprintf(i-1,a)
		a += .3 * k
	end for
	a = wait_key()
end for

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu