Trig value errors

S

Seebs

I use a Linux calculator named Qaculate.
I do not know the people who designed and
coded it, but it makes me happy. Why?

Because it's not using IEEE 754 floats.
So I am asking you to see that these errors be fixed.

And we have been asking you to please LEARN TO READ.

All your ranting misses the point.

THE RESULTS YOU ARE GETTING ARE MANDATED BY AN INTERNATIONAL STANDARD,
AND EVERY PIECE OF MATHEMATICAL CODE WRITTEN IN ANY LANGUAGE FOR THE LAST
TWO DECADES WHICH DOES NOT PROVIDE ITS OWN ARITHMETIC LIBRARIES FOR
SPECIAL PURPOSES HAS ONLY BEEN TESTED WITH THESE RESULTS FROM THESE
INPUTS.

Changing this would break EVERYTHING.

Here's a suggestion: Write a class which provides the semantics you want,
and use it instead of floating point numbers. The semantics of floating
point values are very rigidly defined, and failure to generate the exact
same behaviors as other systems would be MUCH worse than generating answers
which have miniscule rounding errors.

-s
 
J

John W Higgins

[Note: parts of this message were removed to make it a legal post.]

Respectifully........

All that is necessary is that
you CARE enough that it does it.

It would make me very happy if I could share my code, and
not have to include patches and redefinitions in it just
to assure other people get the same (exact) results I do.

I agree with your Principle of Least Surprises (POLS).

The language should work to please the user.
The language should be intuitive to the user.
The language should not cause unnecessary surprises.

So please, fix these errors.

This will make me happy.
What would make pretty much everyone on this list happy is if you took 1/10
the amount of time you've spent calling the Ruby community idiots actually
investigating why your tool of choice works better than you are getting from
the C STANDARD (note that nasty 8 letter word again) library. I took a 1
minute look at the Qalculate website and discovered that it uses the CLN
library for its math functions. Apparently that library has a higher degree
of precision that the C STANDARD library used by Ruby.

Shockingly choices are made that have nothing to do with people caring or
not. Clearly since a number of folks have decided to attempt to assist you
in even with your ignorant rant against the community we must care about
even the ignorant amongst us.

You may feel absolutely free to build an extension to access the library.

Also, taking another 2 minutes to investigate just a bit further I came
across a post from matz himself discussing this exact library (along with
GMP - another alternative).
http://osdir.com/ml/ruby-talk/2009-03/msg01505.html The problem is that
LEGALLY they cannot link a pure GPL library into ruby because of licensing
issues. Again, sometimes decisions are made that affect 1% of the user base
that are unfortunate but unless you step up and help (and bitching isn't
helping) - you are never going to get what you want. BTW, there appears to
be at least some form of an extension to access GMP which may be of
assistance to you -
http://t-a-w.blogspot.com/2007/08/resurrection-of-libgmp-ruby.html

Please step up yourself and assist the community in gaining access to more
precise mathematical functionality rather than making unfounded and
exceptionally ignorant accusations. No one years ago got a big chuckle out
of placing barriers to someone's future attempt to use sin and cos - we're
just plugging along doing the best we can.

John
 
P

Phrogz

This didn't nullify THE POINT I illustrated, which was
using an increasingly smaller angle approaching zero as
an argument, it eventually produced a value of '1' for
cos, but not '0' for the same sin angle, as it should.

No, it didn't produce a value of 1. Look at the second part of my
post, which you quoted, at the top of this message.
 
B

Benoit Daloze

[Note: parts of this message were removed to make it a legal post.]

If you want more precision, you could use BigDecimal (and BigMath).
Then you would get something like:

irb(main):025:0> p=2000; cos(PI(p)/2, p).to_s
=> "0.64773210554205705...E-2016"
irb(main):026:0> p=2000; sin(PI(p)/2, p).to_s
=> "0.99999999999999999999999999999999999999...E0"

Well, I think it's safe to round the 2016th decimal, isn't it ?
Also rounding a ton of 9.

So, rounding to the precision(2000), you get what you want.

irb(main):036:0> p=20; cos(PI(p)/2, p).round(p).to_f
=> 0.0
irb(main):037:0> p=20; sin(PI(p)/2, p).round(p).to_f
=> 1.0

And well, you really don't need 2000 of precision, 20 is far enough in this
case.
 
P

Phillip Gawlowski

On 23.12.2009 18:42, jzakiya wrote:
[...]
This makes me happy. [...]
This makes me happy. [...]
This makes me happy. [...]

This makes me unhappy. [...]
So please, fix these errors.

This will make me happy.
[...]

Bluntly speaking, your happiness is your probem, and not relevant to me,
Matz, or indeed anyone.

If you don't like the result Ruby provides, *do something constructive*.
Bitching and yapping about minute details, the reasoning for which have
been put before you more often than to be expected (i.e. more than
once), will earn you increasing animosity, if not hostility.

If you don't like how Ruby does math, feel free to investigate
alternatives to Ruby, or write a math library that does its calculations
to the level of accuracy that makes you happy.

Nobody forces you to use Ruby (unless it is your employer, in which case
I'd suggest investigating alternative employment, nice as Ruby is).

You could use JRuby and a Java library with "better" maths; you could
use IronRuby and a .NET library with "better" maths.

Nobody forces you to use Ruby as *is*, either. It's open source. Change
Ruby's behavior, if you like.
 
P

Phillip Gawlowski

Now that we're thoroughly off topic :)

My pleasure. ;)
There isn't a single field of research that yields practical
application who's core isn't founded in some sort of math. I'm not a
mathematician (or even a math major) but my understanding has always
been that maths have been *discovered*, not necessarily *invented*.

I have to disagree. While physics, or chemistry, uses math to yield
results of some form (statistics, for example, to evaluate an
experiment), you could replace math with something, if you so desired.

Essentially, what happens in physics happens whether there is math or not.

Of course, since math is very, very useful, it rose to the level of
prominence it has achieved in all the siences. It is, however, not the
driving factor behind these discoveries.

But be that as it may, math *is* a science, and leads to mathematical
discoveries. However, these discoveries are true in the framework "we"
(i.e. the body of human work in the sciences, *including* maths) arrived at.

In any case, math has its beauty (even if a lot of it will forever be
closed to me, since I lack the knowledge and the will to investigate it
deeper than I have to), and thus can be valued in and of itself. :)

And thusly, I'll keep my mouth shut about the topic now, but if further
discussion is desired, I'm more than happy to continue it off-list. :)
 
J

jzakiya

Also, as an example:

static VALUE
math_cos(VALUE obj, VALUE x)
{
    Need_Float(x);
    return DBL2NUM(cos(RFLOAT_VALUE(x)));

}

If you have a beef with anyone, its with the implementers of the C
standard library, but...

Try this (with correct syntax if wrong).
Do similar for sin.

static VALUE
math_cos(VALUE obj, VALUE x)
{
Need_Float(x);
cos_value = DBL2NUM(cos(RFLOAT_VALUE(x)));
if (abs(cos_value) < 1e-10) cos_value 0.0;
return cos_value;
}
 
S

Seebs

Try this (with correct syntax if wrong).
Do similar for sin.
static VALUE
math_cos(VALUE obj, VALUE x)
{
Need_Float(x);
cos_value = DBL2NUM(cos(RFLOAT_VALUE(x)));
if (abs(cos_value) < 1e-10) cos_value 0.0;
return cos_value;
}

That'd be exceptionally stupid.

Here's the problem: There exists at least one value for which the correct
value of cos(x) is about 9e-11, which can be correctly represented (within
a much, much, smaller margin of error) in a floating point value, and which
you would then "fix" by changing it from not-zero to exactly-zero.

Which is to say, this would introduce a comparatively HUGE error, much larger
than the alleged error you're complaining about.

If you want approximate values, round them.

-s
 
J

jzakiya

Try this (with correct syntax if wrong).
Do similar for sin.

static VALUE
math_cos(VALUE obj, VALUE x)
{
    Need_Float(x);
    cos_value = DBL2NUM(cos(RFLOAT_VALUE(x)));
    if (abs(cos_value) < 1e-10) cos_value  0.0;
    return cos_value;
}

please Excuse the typo:

if (abs(cos_value) < 1e-10) cos_value = 0.0;
 
J

jzakiya

That'd be exceptionally stupid.

Here's the problem:  There exists at least one value for which the correct
value of cos(x) is about 9e-11, which can be correctly represented (within
a much, much, smallermargin of error) in a floating point value, and which
you would then "fix" by changing it from not-zero to exactly-zero.

Which is to say, this would introduce a comparatively HUGE error, much larger
than the alleged error you're complaining about.

If you want approximate values, round them.

-s
Here's the problem: There exists at least one value for which the correct
value of cos(x) is about 9e-11, which can be correctly represented (within)

And what (extremely small) angle(s) would that be?
Provide examples please:

If so then do:

if (abs(cos_value) < 1e-14) cos_value = 0.0;

This provides the correct answers for the errors I illustrated.

This makes me happy. :)
 
S

Seebs

And what (extremely small) angle(s) would that be?

Are you really this stupid?
if (abs(cos_value) < 1e-14) cos_value = 0.0;
This provides the correct answers for the errors I illustrated.

Again:

If you can measure, in a float, the amount of the error, then there exists
a value for which that number is closer than 0, and you're introducing
an error larger than you're correcting.
This makes me happy. :)

Have you considered masturbating in public? It would also make you happy,
and be easier for other people to ignore.

Again:

If you want rounded values, round them yourself. You've just demonstrated
that you know how to round (albeit poorly). Great. When you want rounded
values, you go ahead and round them, then.

-s
 
P

pharrington

Are you really this stupid?


Again:

If you can measure, in a float, the amount of the error, then there exists
a value for which that number is closer than 0, and you're introducing
an error larger than you're correcting.


Have you considered masturbating in public?  It would also make you happy,
and be easier for other people to ignore.

Again:

If you want rounded values, round them yourself.  You've just demonstrated
that you know how to round (albeit poorly).  Great.  When you want rounded
values, you go ahead and round them, then.

-s

Let him break his Ruby install if he wants. Best to learn through
experience.
 
S

Seebs

Let him break his Ruby install if he wants. Best to learn through
experience.

Yeah, but he seems to want to know why we aren't all rushing to fix a
couple of special cases.

(Hint to the OP: You're fixing "180", but not "179.99999" or "180.0000001".)

-s
 
C

Colin Bartlett

As a general comment: "MINASWAN", or to be precise "MINASWA mostly N"
"And your Mom, too." Ruby-talk best practices
http://blog.rubybestpractices.com/posts/jamesbritt/and_your_Mom_too.html

And now thoroughly OT:

Not necessarily a bad thing! :)
My pleasure. ;)

I have to disagree. While physics, or chemistry, uses math to yield results
of some form (statistics, for example, to evaluate an experiment), you could
replace math with something, if you so desired.
Essentially, what happens in physics happens whether there is math or not.

A mathematician (I think Ian Stewart) has observed that the physicists
would have derived the parts of group theory that they needed if
it hadn't been previously derived by the mathematicians.
And thusly, I'll keep my mouth shut about the topic now, but if further
discussion is desired, I'm more than happy to continue it off-list. :)

Same here: I think my email address is visible?
I even have an (ancient) mathematical joke to illustrate the points,
which I hesitate to inflict on ruby-talk in general.

Colin Bartlett
 
P

Paul Smith

As a general comment: "MINASWAN", or to be precise "MINASWA mostly N"
=A0"And your Mom, too." Ruby-talk best practices
=A0http://blog.rubybestpractices.com/posts/jamesbritt/and_your_Mom_too.ht=
ml

Nice post, but I think I found a typo where a 'not' is missing:

And being wrong on one thing does make make a person wrong on everything.

--=20
Paul Smith
http://www.nomadicfun.co.uk

(e-mail address removed)
 
B

Brian Candler

The answers given by sin() and cos() are already the most accurate which
could be provided given the constraints of floating-point
representation.

Why would you want to make them less accurate? Surely it would be a bug
if the values returned were less accurate than the representation
allows?

Floating-point can represent smaller increments the closer you get to
zero. So values of 0 +/- dX can be represented much more accurately than
1 +/- dX.
 
S

Seebs

Why would you want to make them less accurate? Surely it would be a bug
if the values returned were less accurate than the representation
allows?

Because our hero is obsessed with the unrounded results of
intrinsically-rounded cases, and hasn't thought about the question
of whether, say, sin(45) or sin(60) is returning "exactly" the
right value. Special-casing zeroes implies a deep failure to
understand trig.

-s
 
R

Rick DeNatale

Floating-point can represent smaller increments the closer you get to
zero. So values of 0 +/- dX can be represented much more accurately than
1 +/- dX.

Strictly speaking they can be represented much more precisely.

Precision and accuracy are different things.

http://en.wikipedia.org/wiki/Accuracy_and_precision


--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale
 
R

Robert Klemme

Strictly speaking they can be represented much more precisely.

Are you sure you meant "precisely" and not "accurately"? Given the
Wikipedia article you quote it seems _that_ is what you rather wanted to
say.
Precision and accuracy are different things.

http://en.wikipedia.org/wiki/Accuracy_and_precision

In light of the article the term "precision" (aka "repeatability") is
pretty meaningless in this case (you could also say "uninteresting")
because due to the deterministic nature of the implementation of
trigonometric functions the result is always identical for the same
input. It is the accuracy that the whole thread revolves around. IEEE
standards mandate a certain accuracy and people who need better accuracy
need to use specialized tools - either math libraries with higher
accuracy (or even selectable accuracy) or tools that do symbolic math.

Also, as elsewhere in this thread has been explained, the "correction"
approach suggested (if the abs is lower than a particular epsilon,
return 0 instead of the value) is a pretty bad one - much worse than
general rounding of values because it introduces distorted accuracy.
Rounding is better because it generally cuts off digits; which is ironic
because it *reduces* overall accuracy of the function...

Kind regards

robert


A program that nicely demonstrates the nonlinearity of the error
introduced by the suggested "fix":

module Math
def sin2(x, epsilon = 1e-10)
y = sin(x)
y.abs < epsilon ? 0.0 : y
end
end

include Math

# find interesting start value
div = 1.2
x = 1.0
x /= div while sin(x) == sin2(x)

x *= div ** 10

# do the test
100.times do |i|
y1 = sin(x)
y2 = sin2(x)
printf "%6d %20e %20e %20e error: %20e\n", i, x, y1, y2, ((y2-y1)/x).abs
x /= div
end
 
R

Rick DeNatale

Are you sure you meant "precisely" and not "accurately"? =A0Given the
Wikipedia article you quote it seems _that_ is what you rather wanted to
say.
No I meant what I said, although I might have picked a better source to quo=
te.

Precision refers to the smallest increment between floating point
numbers, the smaller the exponent the smaller the value of the least
sign, so one might be able to represent both

0.000000001
and
0.000000002

but, say

10000000.000000001 would have to be represented as

10000000.00
because you only have so many digits


Now one might compute a value of Pi

as

3.14
which would be more accurate, although less precise than a
miscalculated value like
4.3259890880890

One of the mistaken notions of novice programmers is to expect that
large amounts of precision in floating point arithmethic are always
good. However, in doing calculations with physical measurements of
various precisions, one can't get any better precision than what you
start with. One can be fooled that the low order digits of
calculations represent precision that really isn't there, and if one
isn't careful about things like the order of floating point operations
when dealing with either very close or very distant values, accuracy
can easily be lost.

http://docs.sun.com/source/806-3568/ncg_goldberg.html





--=20
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top