LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 05-22-2006, 01:08 PM   #1
chief_officer
Member
 
Registered: Mar 2006
Location: Istanbul, TR
Distribution: Red Hat, CentOS, Ubuntu
Posts: 181

Rep: Reputation: 30
[Java] Sines, cosines and tangents. One is wrong...


Friends,

I am trying to put some lines of codes to learn java and following is what I've ran into today...

I was trying to get the basics of trigonometric operations. I coded a small script to display me the sines from 0 to <360 in 30 degree increments. As we all know, sines from 0 to 180 [or 0 to pi) are positive. For sin(30) and sin(60) I got negative values. Similar things went on for cos. So, knowing that tan(x)=sin(x)/cos(x), I have written the following code for testing:

Code:
package javaapplication4;

public class Main {
    
    public Main() {
    }
    
    public static void main(String[] args) {
        int x; double t;
        
    for (x=0; x<360; x += 30)
    {
        double sin_x = Math.sin(x);
        double cos_x = Math.cos(x);
        double tan_x = Math.tan(x);
        System.out.println("Sin(" +x +")" +"=" +sin_x);
        System.out.println("Cos(" +x +")" +"=" +cos_x);
        t = sin_x / cos_x;
        
            if (t == tan_x)
            {
            System.out.println("True");
            }
            else System.out.println("False");
    }
        
    }
    
}
The output is:

Code:
init:
deps-jar:
compile-single:
run-single:
Sin(0)=0.0
Cos(0)=1.0
True
Sin(30)=-0.9880316240928618
Cos(30)=0.15425144988758405
False
Sin(60)=-0.3048106211022167
Cos(60)=-0.9524129804151563
False
Sin(90)=0.8939966636005579
Cos(90)=-0.4480736161291702
False
Sin(120)=0.5806111842123143
Cos(120)=0.8141809705265618
False
Sin(150)=-0.7148764296291646
Cos(150)=0.6992508064783751
True
Sin(180)=-0.8011526357338304
Cos(180)=-0.5984600690578581
True
Sin(210)=0.46771851834275896
Cos(210)=-0.8838774731823718
True
Sin(240)=0.9454451549211168
Cos(240)=0.32578130553514806
False
Sin(270)=-0.1760459464712114
Cos(270)=0.9843819506325049
True
Sin(300)=-0.9997558399011495
Cos(300)=-0.022096619278683942
True
Sin(330)=-0.13238162920545193
Cos(330)=-0.9911988217552068
True
BUILD SUCCESSFUL (total time: 0 seconds)
So, let's see the oddities:

1. Sine of any degree between 0 and 90 (0 to pi/2) can't be negative
2. Cosine of any degree 0 and 90 (0 to pi/2) can't be negative
3. Cos(90) (or cos(pi/2)) ==0

And finally, from the code sin(x)/cos(x) != tan(x)



Can anyone tell me what I am missing? I believe I am making a very small mistake that confuses me.

If it helps, I am running JDK 5 with Netbeans (latest version, I downloaded yesterday: 21MAY06 SUN) on SuSE 9.3 Pro.

Regards,
 
Old 05-22-2006, 01:18 PM   #2
Centinul
Member
 
Registered: Jun 2005
Distribution: Gentoo
Posts: 552

Rep: Reputation: 30
Just out of curiousity. Is the code taking input as RADIANS or DEGREES?
 
Old 05-22-2006, 01:24 PM   #3
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,379

Rep: Reputation: 148Reputation: 148
Trig function normally use radians so I would suspect that you need to convert your degree to radians before using the functions.
 
Old 05-22-2006, 01:25 PM   #4
Centinul
Member
 
Registered: Jun 2005
Distribution: Gentoo
Posts: 552

Rep: Reputation: 30
graemef---

That's my guess.
 
Old 05-22-2006, 01:32 PM   #5
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,379

Rep: Reputation: 148Reputation: 148
Should add that to convert to radians you need to multiply by pi and then divide by 180, that means that you want to work with floating point values.
 
Old 05-23-2006, 12:15 AM   #6
ppanyam
Member
 
Registered: Oct 2004
Location: India
Distribution: Redhat
Posts: 88

Rep: Reputation: 15
In java, all the Math trig functions are static, take double value radians as arguments and return double values and return radian values ( not angles in degrees) for inverse trig. functions.

So in your problem,

double rad = angle * Math.PI/ 180.0;
double val = Math.cos(rad);

will work fine.


ppanyam
 
Old 05-23-2006, 01:40 AM   #7
ppanyam
Member
 
Registered: Oct 2004
Location: India
Distribution: Redhat
Posts: 88

Rep: Reputation: 15
Also, it is not a great idea to compare 2 floating point numbers.. Even if there is a difference in 43 rd decimal, it will return false. You must google some article on floating point number comparison to know the pitfalls.

ppanyam
 
Old 05-23-2006, 03:56 AM   #8
chief_officer
Member
 
Registered: Mar 2006
Location: Istanbul, TR
Distribution: Red Hat, CentOS, Ubuntu
Posts: 181

Original Poster
Rep: Reputation: 30
Thank you very much to all of you for your posts.

@Centinul: the code is taking degrees as input.

@graemef: It shouldn't have mattered, whether degrees or radians I suppose.

@graemef & ppanyam: I will try tonight with the radian conversion and post the results here.

@ppanyam: I just wanted to make sure that there's an error with the results of sines and cosines. My intention was not to compare the two results, but to prove myself that there's something wrong.
 
Old 05-23-2006, 06:46 AM   #9
Centinul
Member
 
Registered: Jun 2005
Distribution: Gentoo
Posts: 552

Rep: Reputation: 30
chief_officer --

I just wanted to say good luck When I said that above I meant what the actual function SHOULD take as input not what is was taking for input. Sorry for confusion
 
Old 05-23-2006, 01:12 PM   #10
chief_officer
Member
 
Registered: Mar 2006
Location: Istanbul, TR
Distribution: Red Hat, CentOS, Ubuntu
Posts: 181

Original Poster
Rep: Reputation: 30
I'm continuing this post so other people can benefit from this nice discussion.

@Centinul: No need to be sorry.

@graemef & ppanyam: As I said I rushed home and tried with your suggestions. Here is the modified version of my code:

Code:
package javaapplication4;

public class Main {
    
    public Main() {
    }
    
    public static void main(String[] args) {
        int x; double t;
        
    for (x=0; x<=360; x += 30)
    {
        double rad = x * Math.PI/180;
        double sin_x = Math.sin(rad);
        double cos_x = Math.cos(rad);
        double tan_x = Math.tan(rad);
        t = sin_x / cos_x;
        System.out.println("Sin(" +x +")" +"=" +sin_x);
        System.out.println("Cos(" +x +")" +"=" +cos_x);
        System.out.println("Tan(" +x +")" +"=" +tan_x);
        System.out.println("Computed tan(" +x +")" + "=" +t);
        
            if (t == tan_x)
            {
            System.out.println("True");
            }
            else System.out.println("False");
    }
        
    }
    
}
Beware that I'm using radians for computation and degrees for displaying the angles [if you have gone through degrees in all your math classes, radians do not seem friendly]. And I have also modified the x variable slightly. Now it's not less than 360 but less than or equal to.

The output is as follows:

Code:
Sin(0)=0.0
Cos(0)=1.0
Tan(0)=0.0
Computed tan(0)=0.0
True
Sin(30)=0.49999999999999994
Cos(30)=0.8660254037844387
Tan(30)=0.5773502691896257
Computed tan(30)=0.5773502691896256
False
Sin(60)=0.8660254037844386
Cos(60)=0.5000000000000001
Tan(60)=1.7320508075688767
Computed tan(60)=1.7320508075688767
True
Sin(90)=1.0
Cos(90)=6.123233995736766E-17
Tan(90)=1.633123935319537E16
Computed tan(90)=1.633123935319537E16
True
Sin(120)=0.8660254037844387
Cos(120)=-0.4999999999999998
Tan(120)=-1.7320508075688783
Computed tan(120)=-1.732050807568878
False
Sin(150)=0.49999999999999994
Cos(150)=-0.8660254037844387
Tan(150)=-0.5773502691896257
Computed tan(150)=-0.5773502691896256
False
Sin(180)=1.2246467991473532E-16
Cos(180)=-1.0
Tan(180)=-1.2246467991473532E-16
Computed tan(180)=-1.2246467991473532E-16
True
Sin(210)=-0.5000000000000001
Cos(210)=-0.8660254037844386
Tan(210)=0.577350269189626
Computed tan(210)=0.577350269189626
True
Sin(240)=-0.8660254037844385
Cos(240)=-0.5000000000000004
Tan(240)=1.7320508075688754
Computed tan(240)=1.7320508075688754
True
Sin(270)=-1.0
Cos(270)=-1.8369701987210297E-16
Tan(270)=5.443746451065123E15
Computed tan(270)=5.443746451065123E15
True
Sin(300)=-0.8660254037844386
Cos(300)=0.5000000000000001
Tan(300)=-1.732050807568877
Computed tan(300)=-1.7320508075688767
False
Sin(330)=-0.5000000000000004
Cos(330)=0.8660254037844384
Tan(330)=-0.5773502691896264
Computed tan(330)=-0.5773502691896265
False
Sin(360)=-2.4492935982947064E-16
Cos(360)=1.0
Tan(360)=-2.4492935982947064E-16
Computed tan(360)=-2.4492935982947064E-16
Now, all seems fine, except the following:

1. The code can display zeroes fine, as we see in 0 degrees [or 0 radians]. However, this is not sometimes the case. Check out Cos(270) [or Cos(3*PI/2)]. It should be definitely zero. But it is displayed as something very very close to zero. And the sign is negative. Is it implicitly taking the lim (x->2*PI/3-) cos(x)? Seems so

2. Tan(90) [or Tan(PI/4)] is +infinity. In our output, it is 1.633123935319537E16, which is a close resemblance of +infinity. Is this the case the outputs are handled? Just out of curiosity.

I am asking all these questions and bothering you all, because I wonder why the outputs are displayed with slight + or - values? Just because they are double? I don't think so. If that was the case, Cos(0) wouldn't be displayed as 1.0 I think. Just see Sin(30)=Cos(60), which is 0.5 but once it is 0.49999999999999994 and then 0.5000000000000001.

@ppanyam: The output is the proof of your last post, which you said "Also, it is not a great idea to compare 2 floating point numbers.. Even if there is a difference in 43 rd decimal, it will return false.". Just check out the Tan(300)=-1.732050807568877 and Computed tan(300)=-1.7320508075688767 and your point is obvious.
 
Old 05-23-2006, 01:33 PM   #11
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,379

Rep: Reputation: 148Reputation: 148
For display purposes you probably want to round the value first. Since math.round() returns an integer (unless there is a floating point function that performs rounding) you may want to scale round and then scale back. For example if you want hold 1.6331239 to three decimal places, scale by multiplying by 10 to the power 3 giving 1633.1239, then round giving 1633 and the divide by 10 to the power 3 giving 1.633. When it comes to numbers like 0.4999999 you will get .5 and 6.123E-17 will become zero.
 
Old 05-23-2006, 06:48 PM   #12
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Hi -

I'm a huge fan of Java. But there are important issues involving numeric programming that (sadly) far too few programmers are aware of. These issues have to do with floating point in *ANY* programming language. Some languages are better (Fortran, anybody?) and some are worse (Visual Basic, for example); Java kind falls in the middle.

Anyway, please read this article:
http://www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf
 
Old 05-23-2006, 07:14 PM   #13
jlinkels
LQ Guru
 
Registered: Oct 2003
Location: Bonaire, Leeuwarden
Distribution: Debian /Jessie/Stretch/Sid, Linux Mint DE
Posts: 5,195

Rep: Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043
Uhm... is this language dependent or dependent on how well a library is implemented?

If I am not mistaken, a sine or cosine and all other mathematic functions on a computer are calculated, by doing a series of addtions of fractions (Taylor series?). Not sure, I only know the expression in Dutch. Anyway, this involved a whole lot of additions and divisions in floating point arithmetic. Any outcome is just an approximation of the final value. The approximation is better and the error smaller if the series is longer. Even in algebra, the outcome is not quite exact. In computers the error due floating point accuracy errors is added to the inaccuracy of the outcome.

Taking this into account, and error of 1E-15 is not bad at all. It cannot be exact by nature.

jlinkels
 
Old 05-23-2006, 08:18 PM   #14
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Hi, jlinkels -

One could make a case that the "java.Math" *is* part/parcel of the Java language.

You're absolutely correct: "1E-15" *isn't* bad, and "It cannot be exact by nature". All true.

But nevertheless, there are serious problems with both the Java language (how floating point values are represented, for example) and with the standard libraries. Here's another article that might be of interest:

http://www.research.ibm.com/journal/sj/391/moreira.html

I hasten to add is that these are NOT issues most programmers are ever likely to encounter.

Nor are these issues only applicable to Java: many other languages have similar - or far worse - shortcomings!

IMHO .. PSM

PS:
Yes, you're correct: "Taylor Series" is the term in English.

Last edited by paulsm4; 05-23-2006 at 08:19 PM.
 
Old 05-23-2006, 09:17 PM   #15
jlinkels
LQ Guru
 
Registered: Oct 2003
Location: Bonaire, Leeuwarden
Distribution: Debian /Jessie/Stretch/Sid, Linux Mint DE
Posts: 5,195

Rep: Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043
You know, I am the generation that used to include a punch card with JCL statements in the card deck to link in the NAG library to my FORTRAN program, and then run it on an IBM 370 mainframe...

You could link another library in as well, if you thought it gave better performance or accuracy.


I see what you mean now and how JAVA is different.

jlinkels
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Mondrian OLAP+JAVA: whats wrong with my command line? zakidad Programming 4 06-14-2005 03:40 AM
FC3 installed Limewire crashes with wrong Java version arst05 Fedora 10 03-21-2005 12:32 PM
my time is wrong and calender is also wrong Paxmaster Linux - General 6 12-16-2004 12:46 AM
Can anyone help me to identify what is wrong with this Java code? babyboss Programming 2 10-03-2004 11:28 AM
Shell says wrong Java version.. pipelok-j Linux - Software 2 06-16-2004 06:32 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 06:28 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration