1. atom = problem?

Can someone make the following code work?

include misc.e

atom a
a = tan(10.5)
pretty_print(1, a, {0})
printf(1, "\n%.60f\n", a)

if a = 1.8498999934219273466595723220962099730968475341796875 then
    puts(1, "EQUAL\n")
else
    puts(1, "NOT EQUAL\n")
end if


The result I get here w/3.2 or 3.1.1 is:

$ exu test.e 
1.849899993
1.849899993421927346659572322096209973096847534179687500000000
NOT EQUAL

I'm having problems with unit testing because of this.

Thanks!

--
Jeremy Cowgar
http://jeremy.cowgar.com

new topic     » topic index » view message » categorize

2. Re: atom = problem?

Jeremy Cowgar wrote:
> 
> Can someone make the following code work?
> 
> }}}
<eucode>
> include misc.e
> 
> atom a
> a = tan(10.5)
> pretty_print(1, a, {0})
> printf(1, "\n%.60f\n", a)
> 
> if a = 1.8498999934219273466595723220962099730968475341796875 then
>     puts(1, "EQUAL\n")
> else
>     puts(1, "NOT EQUAL\n")
> end if
> </eucode>
{{{

> 
> The result I get here w/3.2 or 3.1.1 is:
> 
> $ exu test.e 
> 1.849899993
> 1.849899993421927346659572322096209973096847534179687500000000
> NOT EQUAL
> 
> I'm having problems with unit testing because of this.
> 
> Thanks!
> 
> --
> Jeremy Cowgar
> <a href="http://jeremy.cowgar.com">http://jeremy.cowgar.com</a>

It has to do with the limited precision of how floating point numbers are stored
in computer memory.

You cannot test for perfect equality between two floating point values, just a
relative equality (greater or lesser).

We had a discussion about it a ways back. 
http://www.openeuphoria.org/cgi-bin/esearch.exu?thread=1&fromMonth=6&fromYear=C&toMonth=8&toYear=C&keywords=%22Conversion+error%3F%22

--
A complex system that works is invariably found to have evolved from a simple
system that works.
--John Gall's 15th law of Systemantics.

"Premature optimization is the root of all evil in programming."
--C.A.R. Hoare

j.

new topic     » goto parent     » topic index » view message » categorize

3. Re: atom = problem?

Jason Gade wrote:
> 
> It has to do with the limited precision of how floating point numbers are
> stored
> in computer memory. 

So, it has to do with the good old float problem. I had though Euphoria extended
the capability to take care of that problem, but that's OK. I guess I can do the
unit testing like this:

test_equal("message", sprintf("%.10f", func()), sprintf("%.10f", 1.1293843123))


a bit more work, but no problem. Thanks for clarifying.

--
Jeremy Cowgar
http://jeremy.cowgar.com

new topic     » goto parent     » topic index » view message » categorize

4. Re: atom = problem?

Jeremy Cowgar wrote:
> 
> Can someone make the following code work?
> 
> }}}
<eucode>
> include misc.e
> 
> atom a
> a = tan(10.5)
> pretty_print(1, a, {0})
> printf(1, "\n%.60f\n", a)
> 
> if a = 1.8498999934219273466595723220962099730968475341796875 then
>     puts(1, "EQUAL\n")
> else
>     puts(1, "NOT EQUAL\n")
> end if
> </eucode>
{{{

> 
> The result I get here w/3.2 or 3.1.1 is:
> 
> $ exu test.e 
> 1.849899993
> 1.849899993421927346659572322096209973096847534179687500000000
> NOT EQUAL
> 
> I'm having problems with unit testing because of this.
> 
> Thanks!
> 
> --
> Jeremy Cowgar
> <a href="http://jeremy.cowgar.com">http://jeremy.cowgar.com</a>

You shouldn't use string conversion to compare atoms, because of the limited
precision of floating point numbers in hardware.
Use atom_to_float64() in machine.e instead to obtain a sequence of 8 bytes,
which is the internal representation of the number. Then comparing these
sequences of equal length becomes unambiguous.

CChris

new topic     » goto parent     » topic index » view message » categorize

5. Re: atom = problem?

Jeremy Cowgar wrote:
> 
> Jason Gade wrote:
> > 
> > It has to do with the limited precision of how floating point numbers are
> > stored
> > in computer memory. 
> 
> So, it has to do with the good old float problem. I had though Euphoria
> extended
> the capability to take care of that problem, but that's OK. I guess I can do
> the unit testing like this:
> 
> }}}
<eucode>
> test_equal("message", sprintf("%.10f", func()), sprintf("%.10f",
> 1.1293843123))
> </eucode>
{{{

> 
> a bit more work, but no problem. Thanks for clarifying.
> 
> --
> Jeremy Cowgar
> <a href="http://jeremy.cowgar.com">http://jeremy.cowgar.com</a>

Not only Eu doesn't extend reals or integers, but it doesn't guarantee that the
sum of two integers is an integer - a joke, really!
The extension is to be made through an external library, since there is no
hardware support to count on anyway.

CChris

new topic     » goto parent     » topic index » view message » categorize

6. Re: atom = problem?

CChris wrote:
> 
> You shouldn't use string conversion to compare atoms, because of the limited
> precision of floating point numbers in hardware.
> Use atom_to_float64() in machine.e instead to obtain a sequence of 8 bytes,
> which is the internal representation of the number. Then comparing these
> sequences
> of equal length becomes unambiguous.
> 

I'm not following. Here's what I did:

test_equal("atan2() #1",
atom_to_float64(1.283713957607754085898932316922582685947418212890625),
    atom_to_float64(atan2(10.5, 3.1)))


Here's what I get:

failed: atan2() #1. expected: {41,129,149,165,23,138,244,63} but got:
  {42,129,149,165,23,138,244,63}


--
Jeremy Cowgar
http://jeremy.cowgar.com

new topic     » goto parent     » topic index » view message » categorize

7. Re: atom = problem?

Jeremy Cowgar wrote:
> 
> CChris wrote:
> > 
> > You shouldn't use string conversion to compare atoms, because of the limited
> > precision of floating point numbers in hardware.
> > Use atom_to_float64() in machine.e instead to obtain a sequence of 8 bytes,
> > which is the internal representation of the number. Then comparing these
> > sequences
> > of equal length becomes unambiguous.
> > 
> 
> I'm not following. Here's what I did:
> 
> }}}
<eucode>
> test_equal("atan2() #1",
> atom_to_float64(1.283713957607754085898932316922582685947418212890625),
>     atom_to_float64(atan2(10.5, 3.1)))
> </eucode>
{{{

> 
> Here's what I get:
> 
>   failed: atan2() #1. expected: {41,129,149,165,23,138,244,63} but got:
>   {42,129,149,165,23,138,244,63}
> 
> 
> --
> Jeremy Cowgar
> <a href="http://jeremy.cowgar.com">http://jeremy.cowgar.com</a>

I think that your sprintf() version would work better, because comparing the
output of atom_to_float64() is the same as comparing for absolute equality.

Real atoms (as opposed to integer atoms) are stored as doubles and only have
about 15 digits of precision. The scanner converts your long string of digits
into a double representation.

CChris wrote:
> Not only Eu doesn't extend reals or integers, but it doesn't guarantee that
> the sum of two integers is an integer - a joke, really!
> The extension is to be made through an external library, since there is no
> hardware support to count on anyway.

Unless you are running Euphoria on a very, very old machine (386 class) then you
certainly do have hardware FP support. Unless you've built your executable
without it.

What does "doesn't extend reals or integers" mean?

Also, if the sum of two integers exceeds the 31-bit resolution of Euphoria
integers then the sum is automatically promoted to a real atom. I don't know why
that's a joke.

However if a number is defined as an integer and it overflows then you get an
error.

--
A complex system that works is invariably found to have evolved from a simple
system that works.
--John Gall's 15th law of Systemantics.

"Premature optimization is the root of all evil in programming."
--C.A.R. Hoare

j.

new topic     » goto parent     » topic index » view message » categorize

8. Re: atom = problem?

This happens not only on Euphoria or on PC.
In my student times, I programmed calculator CASIO FX-4000 to 
solve hydraulic equations.  One important step is to calculate 
friction factor for using iterative method.

Sometimes the values never converge in the same value, and mus 
to check for a small difference instead check for equally.

Change your code to:
 
if abs(a - 1.8498999934219273466595723220962099730968475341796875) 
   < 0.000001 -- Use really needed precision
then
 
+-+-+-+-+-+-+-+
Marco A. Achury
Caracas, Venezuela

new topic     » goto parent     » topic index » view message » categorize

9. Re: atom = problem?

Marco Achury wrote:
> 
> 
> This happens not only on Euphoria or on PC.
> In my student times, I programmed calculator CASIO FX-4000 to 
> solve hydraulic equations.  One important step is to calculate 
> friction factor for using iterative method.
> 
> Sometimes the values never converge in the same value, and mus 
> to check for a small difference instead check for equally.
> 
> Change your code to:
>  
> if abs(a - 1.8498999934219273466595723220962099730968475341796875) 
>    < 0.000001 -- Use really needed precision
> then
>  
> +-+-+-+-+-+-+-+
> Marco A. Achury
> Caracas, Venezuela

Yes, depending on the magnitude of the number, there is a smallest value,
epsilon, which can actually change that number when added or subtracted.

I had forgotten that I had written limits.e to explore some of these concepts,
with Matt's help.

You can use the functions "next_higher_atom()" and "next_lower_atom" to see if
your result falls into the proper window.

Then again, using limits.e, I would probably do it this way:
-- untested
expect = 1.849899934219273 -- better to use float64_to_atom() if you know your
exact value
result = tan(10.5)
if abs(expect - result) > get_epsilon(result) then -- fails
end if


http://www.rapideuphoria.com/limits.e

--
A complex system that works is invariably found to have evolved from a simple
system that works.
--John Gall's 15th law of Systemantics.

"Premature optimization is the root of all evil in programming."
--C.A.R. Hoare

j.

new topic     » goto parent     » topic index » view message » categorize

10. Re: atom = problem?

Jeremy Cowgar wrote:
> 
> CChris wrote:
> > 
> > You shouldn't use string conversion to compare atoms, because of the limited
> > precision of floating point numbers in hardware.
> > Use atom_to_float64() in machine.e instead to obtain a sequence of 8 bytes,
> > which is the internal representation of the number. Then comparing these
> > sequences
> > of equal length becomes unambiguous.
> > 
> 
> I'm not following. Here's what I did:
> 
> }}}
<eucode>
> test_equal("atan2() #1",
> atom_to_float64(1.283713957607754085898932316922582685947418212890625),
>     atom_to_float64(atan2(10.5, 3.1)))
> </eucode>
{{{

> 
> Here's what I get:
> 
>   failed: atan2() #1. expected: {41,129,149,165,23,138,244,63} but got:
>   {42,129,149,165,23,138,244,63}
> 
> 
> --
> Jeremy Cowgar
> <a href="http://jeremy.cowgar.com">http://jeremy.cowgar.com</a>

Ok, I get it better now.
The problem may lie in how the interpreter parses the string
"1.283713957607754085898932316922582685947418212890625". It won't check all
digits.
I'll check tonight at home using Mathematica, and will tell you more precisely
where the error is.
Oh, by the way, do you get the same issue when using atan2(105,31) instead?
Because there is some imprecision in 3.1, as you know (same old "penny issue").

CChris

new topic     » goto parent     » topic index » view message » categorize

11. Re: atom = problem?

CChris wrote:
> 
> Oh, by the way, do you get the same issue when using atan2(105,31) instead?
> Because there is some imprecision in 3.1, as you know (same old "penny
> issue").
> 

Some will pass, others will not, so... yes, it has to do with imprecision.

--
Jeremy Cowgar
http://jeremy.cowgar.com

new topic     » goto parent     » topic index » view message » categorize

12. Re: atom = problem?

Jason Gade wrote:
> 
> Jeremy Cowgar wrote:
> > 
> > CChris wrote:
> > > 
> > > You shouldn't use string conversion to compare atoms, because of the
> > > limited
> > > precision of floating point numbers in hardware.
> > > Use atom_to_float64() in machine.e instead to obtain a sequence of 8
> > > bytes,
> > > which is the internal representation of the number. Then comparing these
> > > sequences
> > > of equal length becomes unambiguous.
> > > 
> > 
> > I'm not following. Here's what I did:
> > 
> > }}}
<eucode>
> > test_equal("atan2() #1",
> > atom_to_float64(1.283713957607754085898932316922582685947418212890625),
> >     atom_to_float64(atan2(10.5, 3.1)))
> > </eucode>
{{{

> > 
> > Here's what I get:
> > 
> >   failed: atan2() #1. expected: {41,129,149,165,23,138,244,63} but got:
> >   {42,129,149,165,23,138,244,63}
> > 
> > 
> > --
> > Jeremy Cowgar
> > <a href="http://jeremy.cowgar.com">http://jeremy.cowgar.com</a>
> 
> I think that your sprintf() version would work better, because comparing the
> output of atom_to_float64() is the same as comparing for absolute equality.
> 
> Real atoms (as opposed to integer atoms) are stored as doubles and only have
> about 15 digits of precision. The scanner converts your long string of digits
> into a double representation.
> 
> CChris wrote:
> > Not only Eu doesn't extend reals or integers, but it doesn't guarantee that
> > the sum of two integers is an integer - a joke, really!
> > The extension is to be made through an external library, since there is no
> > hardware support to count on anyway.
> 
> Unless you are running Euphoria on a very, very old machine (386 class) then
> you certainly do have hardware FP support. Unless you've built your executable
> without it.
> 
> What does "doesn't extend reals or integers" mean?
> 

There is no builtin provision for integers or reals with more precision bits
than what the hardware supports. No 64-bit integers (you could have them on a
Pentium SSE2), no 128 bit reals, and so on. No multiprecision (real) arithmetic
or calculus, in a nutshell.

> Also, if the sum of two integers exceeds the 31-bit resolution of Euphoria
> integers
> then the sum is automatically promoted to a real atom. I don't know why that's
> a joke.
> 

Because integers are stable by addition, regardless of the magnitude of
operands.

CChris

> However if a number is defined as an integer and it overflows then you get an
> error.
> 
> --
> A complex system that works is invariably found to have evolved from a simple
> system that works.
> --John Gall's 15th law of Systemantics.
> 
> "Premature optimization is the root of all evil in programming."
> --C.A.R. Hoare
> 
> j.

new topic     » goto parent     » topic index » view message » categorize

13. Re: atom = problem?

CChris wrote:
> 
> Jason Gade wrote:
> > CChris wrote:
> > > Not only Eu doesn't extend reals or integers, but it doesn't guarantee
> > > that
> > > the sum of two integers is an integer - a joke, really!
> > > The extension is to be made through an external library, since there is no
> > > hardware support to count on anyway.
> > 
> > Unless you are running Euphoria on a very, very old machine (386 class) then
> > you certainly do have hardware FP support. Unless you've built your
> > executable
> > without it.
> > 
> > What does "doesn't extend reals or integers" mean?
> > 
> 
> There is no builtin provision for integers or reals with more precision bits
> than what the hardware supports. No 64-bit integers (you could have them on
> a Pentium SSE2), no 128 bit reals, and so on. No multiprecision (real)
> arithmetic
> or calculus, in a nutshell.

Ah, gotcha.

> 
> > Also, if the sum of two integers exceeds the 31-bit resolution of Euphoria
> > integers
> > then the sum is automatically promoted to a real atom. I don't know why
> > that's
> > a joke.
> > 
> 
> Because integers are stable by addition, regardless of the magnitude of
> operands.
> 
> CChris

So the only thing that I really see with your comments is that Euphoria behaves
like most other computer languages out there with regards to numerical
limitations. This is not a surprise, and for most applications it's not much of a
limitation.

And there are libraries in the archive for arbitrary precision arithmetic if
that is what your application requires.

--
A complex system that works is invariably found to have evolved from a simple
system that works.
--John Gall's 15th law of Systemantics.

"Premature optimization is the root of all evil in programming."
--C.A.R. Hoare

j.

new topic     » goto parent     » topic index » view message » categorize

14. Re: atom = problem?

/me quietly again suggests "string math" (some in archives) or BCD mode in the
cpu. Presto, no limits to precision. Switching the cpu to BCD mode, assuming it
can be done with the processors Eu will run on, is fastest, of course.

Kat

new topic     » goto parent     » topic index » view message » categorize

15. Re: atom = problem?

Jeremy Cowgar wrote:
> 
> Jason Gade wrote:
> > 
> > It has to do with the limited precision of how floating point numbers are
> > stored
> > in computer memory. 
> 
> So, it has to do with the good old float problem. I had though Euphoria
> extended
> the capability to take care of that problem, but that's OK. I guess I can do
> the unit testing like this:

Actually, it has to do with how floating point numbers are parsed.  I 
recently added scientific.e to parse scientific notation, which gets the
full potential precision.  Regular floating point values are still parsed
the old fashioned way (sufficient for most uses).  We could either switch
over if the number of digits is too long (have to test to find out where
the sweet spot is) or simply use scientific.e for all floating point
parsing.

Change to scientific notation, and you'll get what you expect.  Also, you
have way too much precision there.  Try this:

include misc.e

atom a, b, c, d
a = tan(10.5)
b = 1.8498999934219273466595723220962099730968475341796875
c = 1.8498999934219273
d = 1.8498999934219273e+0

pretty_print(1, a, {0})
printf(1, "\na %1.16f\n", a)
printf(1,   "  %1.16f\n", 1.8498999934219273466595723220962099730968475341796875
)
printf(1,   "b %1.16f\n", b)
printf(1,   "c %1.16f\n", c)
printf(1,   "d %1.16f\n", d)
if a = 1.8498999934219273466595723220962099730968475341796875e+0 then
    puts(1, "EQUAL\n")
else
    puts(1, "NOT EQUAL\n")
end if


new topic     » goto parent     » topic index » view message » categorize

16. Re: atom = problem?

CChris wrote:
> 
> You shouldn't use string conversion to compare atoms, because of the limited
> precision of floating point numbers in hardware.
> Use atom_to_float64() in machine.e instead to obtain a sequence of 8 bytes,
> which is the internal representation of the number. Then comparing these
> sequences of equal length becomes unambiguous.

Actually, as long as you use scientific notation, it uses the full precision
available to 64-bit floating point.  We should probably get there will all
floating point.

Matt

new topic     » goto parent     » topic index » view message » categorize

17. Re: atom = problem?

Matt Lewis wrote:
> 
> CChris wrote:
> > 
> > You shouldn't use string conversion to compare atoms, because of the limited
> > precision of floating point numbers in hardware.
> > Use atom_to_float64() in machine.e instead to obtain a sequence of 8 bytes,
> > which is the internal representation of the number. Then comparing these
> > sequences of equal length becomes unambiguous.
> 
> Actually, as long as you use scientific notation, it uses the full precision
> available to 64-bit floating point.  We should probably get there will all
> floating point.
> 
> Matt

Does it? Can't there still be an off-by-one-or-two-LSBs error when converting
from a string to a double? Or for numbers that don't represent perfectly in
binary?

It's been awhile since I've messed around with this now.

--
A complex system that works is invariably found to have evolved from a simple
system that works.
--John Gall's 15th law of Systemantics.

"Premature optimization is the root of all evil in programming."
--C.A.R. Hoare

j.

new topic     » goto parent     » topic index » view message » categorize

18. Re: atom = problem?

> On 28 Apr 2008 at 9:39, Jason Gade wrote (maybe snipped):

> So the only thing that I really see with your comments is that
> Euphoria behaves like most other computer languages out there with
> regards to numerical limitations. This is not a surprise, and for most
> applications it's not much of a limitation.
> 
> And there are libraries in the archive for arbitrary precision
> arithmetic if that is what your application requires.

I remember someone made a package for extended math precision in the 
days of early v2.x -- Antoine something -- from Holland. Maybe this 
still in the archives.

Best,
Euler

-- 
_
_| euler f german
_| sete lagoas, mg, brazil
_| efgerman{AT}gmail{DOT}com
_| -----------------------------
_| Reply preferably to the list,
_| or to the address above. Thx!

new topic     » goto parent     » topic index » view message » categorize

19. Re: atom = problem?

Jason Gade wrote:
> 
> Matt Lewis wrote:
> > 
> > Actually, as long as you use scientific notation, it uses the full precision
> > available to 64-bit floating point.  We should probably get there will all
> > floating point.
> > 
> 
> Does it? Can't there still be an off-by-one-or-two-LSBs error when converting
> from a string to a double? Or for numbers that don't represent perfectly in
> binary?
> 
> It's been awhile since I've messed around with this now.

It's as close as can be made.  Look in the source folder for scientific.e.

Matt

new topic     » goto parent     » topic index » view message » categorize

20. Re: atom = problem?

CChris wrote:
> 
> Jeremy Cowgar wrote:
> > 
> > CChris wrote:
> > > 
> > > You shouldn't use string conversion to compare atoms, because of the
> > > limited
> > > precision of floating point numbers in hardware.
> > > Use atom_to_float64() in machine.e instead to obtain a sequence of 8
> > > bytes,
> > > which is the internal representation of the number. Then comparing these
> > > sequences
> > > of equal length becomes unambiguous.
> > > 
> > 
> > I'm not following. Here's what I did:
> > 
> > }}}
<eucode>
> > test_equal("atan2() #1",
> > atom_to_float64(1.283713957607754085898932316922582685947418212890625),
> >     atom_to_float64(atan2(10.5, 3.1)))
> > </eucode>
{{{

> > 
> > Here's what I get:
> > 
> >   failed: atan2() #1. expected: {41,129,149,165,23,138,244,63} but got:
> >   {42,129,149,165,23,138,244,63}
> > 
> > 
> > --
> > Jeremy Cowgar
> > <a href="http://jeremy.cowgar.com">http://jeremy.cowgar.com</a>
> 
> Ok, I get it better now.
> The problem may lie in how the interpreter parses the string
> "1.283713957607754085898932316922582685947418212890625".
> It won't check all digits. 
> I'll check tonight at home using Mathematica, and will tell you more precisely
> where the error is.
> Oh, by the way, do you get the same issue when using atan2(105,31) instead?
> Because there is some imprecision in 3.1, as you know (same old "penny
> issue").
> 
> CChris

In Mathematica 5.5:
* N[ArTan[105/31],100] results in a string of the expected length, which the one
you parse is a subset of;
* N[ArcTan[10.5,3.1],100] outputs only a few decmals.

This seems to confirm my guess according to which it is the "3.1" in your test
which causes an issue, because 3.1 is not a finite sum of large enough powers of
2. Those sums are the only numbers the hardware can handle loss-less.

CChris

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu