This question already has answers here:
Why does Math.sin() delegate to StrictMath.sin()?
(4 answers)
Closed 8 years ago.
Quick question about the sine function in Java. Does anyone know how the value is computed? I found this question about sin in Java, but that's asking why the sin function isn't wrapped in native code. I'm asking something entirely different. I want to know how the function was implemented. (Since it's wrapped in native code, I can't see it.)
Did they simply implement it from the Taylor series expansion:
sin(x) = x - (x^3)/3! + (x^5)/5! - O(x^7)
I can't look at the code for the Math.sine() function, since it gets wrapped up in native code.
The implementation can be found here(*).
The sin function is approximated by a 13-degree polynomial. That is, a function on the shape
c12x12 + c11x11 + ... + c1x1 + c0x0
on the interval [0,π/4]
The description of the algorithm looks as follows:
33 * Algorithm
34 * 1. Since sin(-x) = -sin(x), we need only to consider positive x.
35 * 2. if x < 2^-27 (hx<0x3e400000 0), return x with inexact if x!=0.
36 * 3. sin(x) is approximated by a polynomial of degree 13 on
37 * [0,pi/4]
38 * 3 13
39 * sin(x) ~ x + S1*x + ... + S6*x
40 * where
41 *
42 * |sin(x) 2 4 6 8 10 12 | -58
43 * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2
44 * | x |
45 *
46 * 4. sin(x+y) = sin(x) + sin'(x')*y
47 * ~ sin(x) + (1-x*x/2)*y
48 * For better accuracy, let
49 * 3 2 2 2 2
50 * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6))))
51 * then 3 2
52 * sin(x) = x + (S1*x + (x *(r-y/2)+y))
53 */
(*) Disclamer: Talking about OpenJDK here
Related
This question already has answers here:
Dividing two integers in Java gives me 0 or 100?
(5 answers)
Closed 2 years ago.
I have two statements in java:
System.out.println(2 * (5 / 2 + 5 / 2 ));
This generate the output 8 but again in next line:
System.out.println(2 * 5 / 2 + 2 * 5 / 2 );
This generate the output 10.
now my confusion is why it generates different output
please someone describe it. thanks
Note, that division between ints generates an int (rounded down).
2 * (5 / 2 + 5 / 2) => 2 * (2 + 2) => 8
2 * 5 / 2 + 2 * 5 / 2 => 10 / 2 + 10 / 2 => 10
To get the exact value, you would have to use floats:
2 * (5.0 / 2 + 5.0 / 2) == 10
Example 1: 50 + (int)(Math.random() * 50) returns an integer between 50 and 99. The maximum number in decimal form being 99.9 recurring.
Example 2:
34 + (int)(Math.random() * 21) returns an integer between 34 and 55.
The maximum number in decimal form being 54.9 recurring.
Why is it that example 2 returns 55 and not 54?
Math.random() returns a decimal in the range of [0.0, 1.0),
So your assumptions are correct in each example
For the first example, 50 + 49.9 = 99.9
For the second example, 34 + 20.9 = 54.9
I am not sure where you are getting 55 for example two because when the decimal is cast to an int, the decimal will lose its precision, effectively rounding it down to create the max of 99 for example 1 and 54 for example 2
Edit
The book is wrong, if you wanted the range to be 34 to 55, the code would have to be
34 + (int)(Math.random() * 22)
I assume this is from a textbook or tutorial? The second example is wrong. It should say "34 to 54", just like you thought it should.
I would like to check if the result is measurable; that is, whether it has a finite number if decimal places. What do i mean?
double x = 5.0 / 9.0; // x = 0.(5)
x is not measurable.
I want to round x to the second digit ( x = 0.56 ), but in such case:
double x = 1.0 / 8.0; // x = 0.125
I don't want to round anything.
So here is my question. How do i decide if the result can be measured or not?
You cannot. That is the reason, why 1.0 / 3 / 100 * 3 * 100 gives you 0.9999...9. You only have so many bits to represent the numbers. You cannot distinguish between the period
1.0 / 3 and a number that actually has 0.3333.....3 as value
The only fractions which will be exactly represented in a binary will be ones where the denominator is a power of two. If your input is two integers for the numerator and denominator then find the prime factorisation of both and remove the common factors. Then check the only remaining factors on the denominator are power of 2. Say if we want to find 56 / 70 this is 2^3 * 7 / ( 2 * 5 * 7) removing common factors gives 2^2 / 5 so that will not work. But 63 / 72 = (7*3^2) / (2^3 * 3^2) = 7 / 2^3 so will be a terminating binary number
If your working in decimal then powers of 2 and 5 on the denominator will be allowed.
In one example from http://leepoint.net/notes-java/data/expressions/precedence.html
The following expression
1 + 2 - 3 * 4 / 5
Is evaluated as
1 + 2 - 3 * 4 / 5
= (1 + 2) - ((3 * 4) / 5)
= 3 - (12/5)
= 3 - 2 The result of the integer division, 12/5, is 2 .
= 1
Then i saw another example from http://www.roseindia.net/java/master-java/operator-precedence.shtml
The following expression
4 + 5 * 6 / 3
is evaluated as
4 + (5 * (6 / 3))
I am slightly confused as to how it is decided which will be evaluated first when * and / are involved. In the examples above, both seem to be difference.
The first example is evaluating 3*5/5 as ((3*4)/5)
Whereas the second example is evaluating 5*6/3 as (5*(6/3))
I know that * and / have precedence over + and - but what about when the expression includes both * and /. And also why are the above two examples showing different approaches? Is one of them wrong?
Edit
public class ZiggyTest {
public static void main(String[] args) {
System.out.println(4 + (5 * (6 / 3)));
System.out.println(4 + ((5 * 6) / 3));
System.out.println(1 + 2 - (3 * (4 / 5)));
System.out.println(1 + 2 - ((3 * 4) / 5));
}
}
The above program produces the output
14
14
3
1
Why are the last two outputs not the same if the first produced the same output.
I am slightly confused as to how it is decided which will be evaluated first when * and / are involved
That's why we have specifications :)
Section 15.7 is the section of the Java Language Specification which deals with evaluation order, and section 15.17 states:
The operators *, /, and % are called the multiplicative operators. They have the same precedence and are syntactically left-associative (they group left-to-right).
So whenever there is A op1 B op2 C and both op1 and op2 are *, / or % it's equivalent to
(A op1 B) op2 C
Or to put it another way - the second linked article is plain wrong in their example. Here's an example to prove it:
int x = Integer.MAX_VALUE / 2;
System.out.println(x * 3 / 3);
System.out.println((x * 3) / 3);
System.out.println(x * (3 / 3));
Output:
-357913942
-357913942
1073741823
That shows the multiplication happening first (leading to integer overflow) rather than the division (which would end up with a multiplication of 1).
Are you sure?
4 + (5 * 6) / 3
4 + 30 / 3
4 + 10
14
4 + 5 * (6 / 3)
4 + 5 * 2
4 + 10
14
They produce the same output because adding the parentheses don't happen to change the result. For your other equation, the parentheses actually do change the result. By removing the parentheses in the equations I solved, the correct path to the result is the first one.
The second one is wrong. See Jon Skeet's answer. Multiplicative operators evaluate left to right. The grouping for:
4 + 5 * 6 / 3
should be
4 + ((5 * 6) / 3).
In this case, though, the wrong grouping
4 + (5 * (6 / 3))
yields the same answer.
Learning about recursion and having trouble with the code posted below, in line 6,
int result=fact(n-1)*n;
When I delete "fact" the program acts like I think it would, printing out:
Factor of 3 6
Factor of 4 12
Factor of 5 20
but with the "fact" in it gives the output below? What is this line doing, and what is "fact" ? thanks everyone.
Factor of 3 6
Factor of 4 24
Factor of 5 120
Factorial is often used as an example of something which can be performed using recursion.
For example, factorial of 5 is calculated as follows:
5! = 5 * 4 * 3 * 2 * 1
Also, there is another way of thinking about it:
5! = 5 * 4!
4! = 4 * 3!
3! = 3 * 2!
2! = 2 * 1!
1! = 1
The way the second series of equalities are written, it can be seen that a factorial can be calculated in a recursive fashion. For example:
5! = 5 * 4! --> 5! = 5 * (4 * 3!) --> 5! = 5 * (4 * (3 * 2!)) --> and so on.
The fact function in the question is performing the factorial function as written in the second series of equalities:
fact(n) = n * fact(n-1);
So, when the fact method is being called, way it is being called can be thought as something like the following:
fact(5) --> fact(5 * fact(4)) --> fact(5 * fact(4 * fact(3))) --> and so on.
Also, it should be noted as Kip points out in the comments, calculating the factorial of a number can be much easily and quickly calculated by iterating over the range of numbers from n to 1 and multiplying it together to calculate the result.
Apparently this is the classic example of recursion using the factorial calculation.
What you're calling fact(N) is usually denoted by N! (by mathematicians, anyway)
n! = n x (n-1) x (n-2) ...
so
5! = 5 x 4 x 2 x 1 = 120
4! = 4 x 3 x 2 x 1 = 24
Incidentally, this may be a little counterintuitive, but 0! is defined as 1
fact(5) = fact(4) * 5
fact(4) = fact(3) * 4
fact(3) = fact(2) * 3
fact(2) = fact(1) * 2
fact(1) = 1
fact(5) = fact(4) * 5 = fact(3) * 4 * 5 = .. = 1 * 2 * 3 * 4 * 5 = 120
Function recuresively calls itself so it unwraps calculation to 1 * 2 * 3 * 4 * 5.
When you remove the call to fact again you are just doing:
println(n * (n-1))
You may want to try doing a factorial with just a loop and see how different the code is.
Recursion can be useful, but, you will be limited in how large of (n) you can call, as you will eventually overflow the stack, since the calculations won't happen until you reach the condition that marks the end of the recursion.
To better understand recursion you can look at this link:
http://en.wikipedia.org/wiki/Recursion_(computer_science)