I wish to calculate limits (calculus) with Java. I have the following class Limit that can calculate limits:
package calculus;
public final class Limit {
private Limit() {
}
public static final double limit(Function function, double approach) {
double below = Limit.limitFromBelow(function, approach);
double above = Limit.limitFromAbove(function, approach);
return below == above ? below : Double.NaN;
}
public static final double limitFromBelow(Function function, double approach) {
for (double d = approach - 10; d <= approach; d = approach
- ((approach - d) / 10)) {
if (function.apply(d) == Double.POSITIVE_INFINITY) {
return Double.POSITIVE_INFINITY;
} else if (function.apply(d) == Double.NEGATIVE_INFINITY) {
return Double.NEGATIVE_INFINITY;
} else if (Double.isNaN(function.apply(d))) {
return function.apply(approach + ((approach - d) * 10));
} else {
if (d == approach) {
return function.apply(d);
} else if (approach - d < 0.00000000001) {
d = approach;
}
}
}
return Double.NaN;
}
public static final double limitFromAbove(Function function, double approach) {
for (double d = approach + 10; d >= approach; d = approach
- ((approach - d) / 10)) {
if (function.apply(d) == Double.POSITIVE_INFINITY) {
return Double.POSITIVE_INFINITY;
} else if (function.apply(d) == Double.NEGATIVE_INFINITY) {
return Double.NEGATIVE_INFINITY;
} else if (Double.isNaN(function.apply(d))) {
return function.apply(approach + ((approach - d) * 10));
} else {
if (d == approach) {
return function.apply(d);
} else if (d - approach < 0.00000000001) {
d = approach;
}
}
}
return Double.NaN;
}
}
However, I was wondering: Is there another way to calculate limits other than exhaustion and recursive testing? Is there a more efficient method?
Your technique is called numerical approximation of a limit. It is widely used, simple to implement, and generally good enough for many applications. It is easy to use because all you need is a function that you can evaluate in order to apply it.
If you want another way, it is called symbolic or algebraic calculation of limits. In this case, you need to have more information than just the capability to evaluate an unknown function. You need to have an entire parse tree expression for a function including an indication of the independent variable. This is more than just the capability to evaluate the function at a given point. One example of this in Python is shown here:
http://scipy-lectures.github.io/advanced/sympy.html#limits
The symbolic style uses real math rules similar to how you might work out the limit by hand using rules of algebra or calculus.
Calculating many limit problems cannot be done numerically, ofter involves symbolic rules, such as L'Hopital's rule, and thererfore you need a symbolic algebra toolset, which aren't so great in java because there is no operation overloading, all the math guys go to python, or maple if you are doing some serious business.
A numerical implementation alone will not be very good, you can't simply use numerical approximations for limmits, once you enter symbolic maths numerical approximations are very limitted to what you can acheive with them, and you need to check for convergence and all sorts of things but anyway I guess you can have a go for what its worth but don't use this in any serious application.
Related
I am working on a problem that seems to require backtracking of some sort. I have a working recursion method but stackOverFlow happens with larger inputs. Could this be solved with an iterative implementation? I am trying to implement a method that takes in two target values a and b. starting with a = 1 and b = 1, how many "adds" would it take to reach the target a and b values? adds can either make a = a + b or b = b + a, but not both.
for example, if target a = 2 and target b = 1, it takes 1 "add". a=1 & b=1, a = a + b = 2.
public static String answer(String M, String F) {
return answerRecur(new BigInteger(M), new BigInteger(F), 0);
}
public static String answerRecur(BigInteger M, BigInteger F, int its) {
if(M.toString().equals("1") && F.toString().equals("1")) {
return "" + its;
}
else if(M.compareTo(new BigInteger("0")) <=0 || F.compareTo(new BigInteger("0")) <=0) {
return "impossible";
}
String addM = answerRecur(M.subtract(F), F, its +1);
String addF = answerRecur(M, F.subtract(M), its +1);
if(!addM.equals("impossible")) {
return addM;
}
if(!addF.equals("impossible")) {
return addF;
}
return "impossible";
}
Recursive backtracking works by going through all candidate steps, do a step, recurse, undo the step.
This means that if a solution takes N items, ideally the recursion depth will not exceed N.
So: an overflow is not expected, probably too much is tried, or even infinitely recurring.
However in your case a BigInteger might be sufficient large and when using small steps (1) one would have a very recursion depth. And every call creates sufficient much. Better would be int or long instead of BigInteger.
In every call you have two candidates:
M.subtract(F)
F.subtract(M)
You evaluate both, one could stop when a result was found.
Also intelligence (of the math!) is missing: nice would be to prevent too many steps, finding as directed as possible a solution. In general this can be achieved by some way of sorting of the (2) candidates.
How one comes at a smart solution? First the math must be readable, what BigInteger is less. Try some sample solutions by hand, and look for a smart approach to order the attempts.
You can cut the recursion short, assuming keeping M and F positive:
if (M.compareTo(BigInteger.ZERO) <= 0 || F.compareTo(BigInteger.ZERO) <= 0) {
return "impossible";
}
if (M.equals(BigInteger.ONE)) {
return String.valueOf(F.intValue() - 1 + its);
}
if (F.equals(BigInteger.ONE)) {
return String.valueOf(M.intValue() - 1 + its);
}
The same can be done with integer division (and modulo):
if (M.compareTo(F) > 0) {
String addM = answerRecur(M.mod(F), F, its + M.divided(F).intValue());
}
Thinking of an iterative solution actually is possible here despite more than one recursive call, but it would not add to the quality.
Remarks:
by java convention one should use f and m for variable names.
is BigInteger really required? It causes a bit awkward code.
I've ran the below code and I think it's correct. However, it just keeps returning stack overflow. When I run it in debug mode, I noticed somehow within the function x%y returns y instead of the remainder which is suppose to be 0. Can someone please help and see why this is?
public class test
{
public static void main (String [] args)
{
System.out.println(gcd(50,10));
}
static double gcd(double x, double y)
{
if (x > y)
{
return gcd(y, x);
}
else if (y <= x && x%y == 0)
{
return y;
}
else
{
return gcd(y, x%y);
}
}
}
Technically speaking, the implementation causes a stack overflow because for the arguments 50 and 10 the recursive calls reach the first and the last case alternatively, causing an infinite recursion. Apparently the algorithm for determining the greatest common divisor is implemented incorrectly; an elaborate presentation of it can be found here. That being said, it might not be a good idea to perform the calculations using the type double; I doubt that the division remainder operator % will behave as expected due to rounding.
java.util.Random.nextDouble() is slow for me and I need something really fast.
I did some google search and I've found only integers based fast random generators. Is here anything for real numbers from interval <0, 1) ?
If you need something fast and have access to Java8, I can recommend the java.utils SplittableRandom. It is faster (~twice as fast) and has better statistical distribution.
If you need a even faster or better algorithm I can recommend one of these specialized XorShift variants:
XorShift128PlusRandom (faster & better)
XorShift1024StarPhiRandom (similar speed, even longer period)
Information on these algorithms and their quality can be found in this big PRNG comparison.
I made an independent Performance comparison you can find the detailed results and the code here: github.com/tobijdc/PRNG-Performance
Futhermore Apache Commons RNG has a performance test of all their implemented algoritms
TLDR
Never use java.util.Random, use java.util.SplittableRandom.
If you need faster or better PRNG use a XorShift variant.
You could modify an integer based RNG to output doubles in the interval [0,1) in the following way:
double randDouble = randInt()/(RAND_INT_MAX + 1.0)
However, if randInt() generates a 32-bit integer this won't fill all the bits of the double because double has 53 mantissa bits. You could obviously generate two random integers to fill all mantissa bits. Or you could take a look at the source code of the Ramdom.nextDouble() implementation. It almost surely uses an integer RNG and simply converts the output to a double.
As for performance, the best-performing random number generators are linear congruential generators. Of these, I recommend using the Numerical Recipes generator. You can see more information about LCGs from Wikipedia: http://en.wikipedia.org/wiki/Linear_congruential_generator
However, if you want good randomness and performance is not that important, I think Mersenne Twister is the best choice. It also has a Wikipedia page: http://en.wikipedia.org/wiki/Mersenne_Twister
There is a recent random number generator called PCG, explained in http://www.pcg-random.org/. This is essentially a post-processing step for LCG that improves the randomness of the LCG output. Note that PCG is slower than LCG because it is simply a post-processing step for LCG. Thus, if performance is very important and randomness quality not that important, you want to use LCG instead of PCG.
Note that none of the generators I mentioned are cryptographically secure. If you need use the values for cryptographical applications, you should be using a cryptographically secure algorithm. However, I don't really believe that doubles would be used for cryptography.
Note that all these solutions miss a fundamental fact (that I wasn't aware of up to a few weeks ago): passing from 64 bits to a double using a multiplication is a major loss of time. The implementation of xorshift128+ and xorshift1024+ in the DSI utilities (http://dsiutils.di.unimi.it/) use direct bit manipulation and the results are impressive.
See the benchmarks for nextDouble() at
http://dsiutils.di.unimi.it/docs/it/unimi/dsi/util/package-summary.html#package.description
and the quality reported at
http://prng.di.unimi.it/
Imho you should just accept juhist's answer - here's why.
nextDouble is slow because it makes two calls to next() - it's written right there in the documentation.
So your best options are:
use a fast 64 bit generator, convert that to double (MT, PCG, xorshift*, ISAAC64, ...)
generate doubles directly
Here's an overly long benchmark with java's Random, an LCG (as bad as java.util.Random), and Marsaglia's universal generator (the version generating doubles).
import java.util.*;
public class d01 {
private static long sec(double x)
{
return (long) (x * (1000L*1000*1000));
}
// ns/op: nanoseconds to generate a double
// loop until it takes a second.
public static double ns_op(Random r)
{
long nanos = -1;
int n;
for(n = 1; n < 0x12345678; n *= 2) {
long t0 = System.nanoTime();
for(int i = 0; i < n; i++)
r.nextDouble();
nanos = System.nanoTime() - t0;
if(nanos >= sec(1))
break;
if(nanos < sec(0.1))
n *= 4;
}
return nanos / (double)n;
}
public static void bench(Random r)
{
System.out.println(ns_op(r) + " " + r.toString());
}
public static void main(String[] args)
{
for(int i = 0; i < 3; i++) {
bench(new Random());
bench(new LCG64(new Random().nextLong()));
bench(new UNI_double(new Random().nextLong()));
}
}
}
// straight from wikipedia
class LCG64 extends java.util.Random {
private long x;
public LCG64(long seed) {
this.x = seed;
}
#Override
public long nextLong() {
x = x * 6364136223846793005L + 1442695040888963407L;
return x;
}
#Override
public double nextDouble(){
return (nextLong() >>> 11) * (1.0/9007199254740992.0);
}
#Override
protected int next(int nbits)
{
throw new RuntimeException("TODO");
}
}
class UNI_double extends java.util.Random {
// Marsaglia's UNIversal random generator extended to double precision
// G. Marsaglia, W.W. Tsang / Statistics & Probability Letters 66 (2004) 183 – 187
private final double[] U = new double[98];
static final double r=9007199254740881.0/9007199254740992.;
static final double d=362436069876.0/9007199254740992.0;
private double c=0.;
private int i=97,j=33;
#Override
public double nextDouble(){
double x;
x=U[i]- U[j];
if(x<0.0)
x=x+1.0;
U[i]=x;
if(--i==0) i=97;
if(--j==0) j=97;
c=c-d;
if(c<0.0)
c=c+r;
x=x-c;
if(x<0.)
return x+1.;
return x;
}
//A two-seed function for filling the static array U[98] one bit at a time
private
void fillU(int seed1, int seed2){
double s,t;
int x,y,i,j;
x=seed1;
y=seed2;
for (i=1; i<98; i++){
s= 0.0;
t=0.5;
for (j=1; j<54; j++){
x=(6969*x) % 65543;
// typo in the paper:
//y=(8888*x) % 65579;
//used forthe demo in the last page of the paper.
y=(8888*y) % 65579;
if(((x^y)& 32)>0)
s=s+t;
t=.5*t;
}
if(x == 0)
throw new IllegalArgumentException("x");
if(y == 0)
throw new IllegalArgumentException("y");
U[i]=s;
}
}
// Marsaglia's test code is useless because of a typo in fillU():
// x=(6969*x)%65543;
// y=(8888*x)% 65579;
public UNI_double(long seed)
{
Random r = new Random(seed);
for(;;) {
try {
fillU(r.nextInt(), r.nextInt());
break;
} catch(Exception e) {
// loop again
}
}
}
#Override
protected int next(int nbits)
{
throw new RuntimeException("TODO");
}
}
You could create an array of random doubles when you init your program and then just repeat it. This is much faster but the random values reapeat themselfs.
Qn (from cracking coding interview page 91)
Numbers are randomly generated and passed to a method. Write a program to find and maintain the median value as new values are generated.
My question is: Why is it that if maxHeap is empty, it's okay to return minHeap.peek() and vice versa in getMedian() method below?
Doesn't this violate the property of finding a median?
I am using the max heap/min heap method to solve the problem. The solution given is as below:
private static Comparator<Integer> maxHeapComparator, minHeapComparator;
private static PriorityQueue<Integer> maxHeap, minHeap;
public static void addNewNumber(int randomNumber) {
if (maxHeap.size() == minHeap.size()) {
if ((minHeap.peek() != null)
&& randomNumber > minHeap.peek()) {
maxHeap.offer(minHeap.poll());
minHeap.offer(randomNumber);
} else {
maxHeap.offer(randomNumber);
}
} else {
if (randomNumber < maxHeap.peek()) {
minHeap.offer(maxHeap.poll());
maxHeap.offer(randomNumber);
} else {
minHeap.offer(randomNumber);
}
}
}
public static double getMedian() {
if (maxHeap.isEmpty()) {
return minHeap.peek();
} else if (minHeap.isEmpty()) {
return maxHeap.peek();
}
if (maxHeap.size() == minHeap.size()) {
return (minHeap.peek() + maxHeap.peek()) / 2;
} else if (maxHeap.size() > minHeap.size()) {
return maxHeap.peek();
} else {
return minHeap.peek();
}
}
The method has a shortcoming that it does not work in situations when both heaps are empty.
To fix, the method signature needs to be changed to return a Double (with the uppercase 'D') Also a check needs to be added to return null when both heaps are empty. Currently, an exception on a failed attempt to convert null to double will be thrown.
Another shortcoming is integer division when the two heaps have identical sizes. You need a cast to make it double - afetr all, that was the whole point behind making a method that finds a median of integers return a double in the first place.
Another disadvantage with this approach is that it doesn't scale well, for example to heap sizes that don't fit in memory.
A very good approximation algorithm is simply storing an approximate median with a fixed increment (eg. 0.10), chosen appropriate to the scale of the problem. For each value, if the value is higher, add 0.10. If the value is lower, subtract 0.10. The result approximates the median, scales well, and can be stored in 4 or 8 bytes.
Just do this ... else everything is correct:
return new Double(minHeap.peek() + maxHeap.peek()) / 2.0;
Before I get into detail, YES this is a HOMEWORK ASSIGNMENT. NO I DON'T WANT ANSWERS, JUST TIPS and/or Suggestions to try this or that.
The problem introduces with this:
Create a class, ExactNumber, that uses two long properties named left
and right (representing the portion of the number that is to the left
and right of the decimal point respectively). For example, 3.75 would
be represented by new ExactNumber(3, 7500000000000000L). Note the L on
the end which tells Java the large number is a long. This translates
to: 3 + 7500000000000000/10000000000000000 = 3.75
Here is my code:
public class ExactNumber {
private long left;
private long right;
public ExactNumber(long left, long right) {
this.left = left;
this.right = right;
}
public String toString() {
return String.valueOf(doubleValue());
}
public double doubleValue() {
return ((double) left + (double) (right/ 100000000000000L) / 100);
}
public int compareTo (ExactNumber exactNumber) {
if(exactNumber.left < left) {
return 1;
}
else if (exactNumber.left == left) {
if (exactNumber.right < right) {
return 1;
}
else if (exactNumber.right == right) {
return 0;
}
else {
return -1;
}
}
else {
return -1;
}
}
public boolean equal(ExactNumber thisobject) {
if (thisobject instanceof ExactNumber) {
if (thisobject.doubleValue() == this.doubleValue()) {
return true;
}
else {
return false;
}
}
else {
return false;
}
}
public double add(ExactNumber exactNumber) {;
return ((left+exactNumber.left) + (double)((right+exactNumber.right)*1E-16));
}
}
My problem are the tests coming up as an error when the expected value is equal to the actual value. Here are the test cases (NOTE: there are more test cases, but they pass the JUnit test):
public class TestExactNumber extends TestCase {
ExactNumber threesevenfive = new ExactNumber(3, 7500000000000000L);
ExactNumber threesevenfive_andalittlebit = new ExactNumber(3, 7500000000000001L);
ExactNumber threesevenfive_dupe = new ExactNumber(3, 7500000000000000L);
ExactNumber ten = new ExactNumber(10, 0);
ExactNumber thirteensevenfive = new ExactNumber(13, 7500000000000000L);
ExactNumber sevenfifty = new ExactNumber(7, 5000000000000000L);
public void test_equals() {
assertFalse(threesevenfive.equals(threesevenfive_andalittlebit));
assertEquals(threesevenfive, threesevenfive_dupe);
}
public void test_add() {
assertEquals(threesevenfive.add(ten), thirteensevenfive);
assertEquals(threesevenfive.add(threesevenfive), sevenfifty);
The assertEquals above failed in the JUnit test, but says like (for an example) expected = 13.75 and actual = 13.75.
Any tips or hints at what I need to do with my code is greatly appreciated. And thank you in advanced.
NOTES:
According to my instructor, I should not be using the doubleValue method to implement my equals method. I know that I do have it in my code, but that was prior to the tip the instructor gave me and I am just unsure about how to change it.
I am using eclipse for java to code this.
Your equal Method is never used. The Java Method used by assertEquals() is called equalS (and you have to override the equals() method derived from Object).
Therefore, the assertion will use equals inherited from Object, which will compare the actual instances rather than using YOUR equal method which will compare the objet values. And since they are two different INSTANCES, they are not equal.
Finally, the two instances will be plotted with toString() resulting in expected = 13.75 and actual = 13.75. (Because your toString() returns only the values, ignoring the difference between instances)
Your Instructors Response:
A Long in Java is a 64 bit long number. Double in Java is implemented with the IEEE754 Standard, which only leaves 52 bit for the mantissa. Meaning: Any conversion of a Long Number to a double, where the Long Number has set bits on bit 53 to 63 - will cause the exponent to be shifted in a way, that you loose precision arround the LSBs - resulting in an unprecice Double Value.
Therefore comparing the double values to determine equality is not sufficent for your desired Design of a "Exact Number".
Example:
Long bigLong = 1L<<51; //picked 51: 52 and 53 already causing rounding issues.
Long long1 = bigLong + 1L;
Long long2 = bigLong + 2L;
System.out.println(long1+" -> " + long1.doubleValue());
System.out.println(long2+" -> " + long2.doubleValue());
//false, enough precision to preserve bit "0" and "1".
System.out.println(long1.doubleValue()==long2.doubleValue());
Output:
2251799813685262 -> 2.251799813685262E15
2251799813685263 -> 2.251799813685263E15
false
When setting bit 54:
Long bigLong = 1L<<54;
Long long1 = bigLong + 1L;
Long long2 = bigLong + 2L;
System.out.println(long1+" -> " + long1.doubleValue());
System.out.println(long2+" -> " + long2.doubleValue());
System.out.println(long1.doubleValue()==long2.doubleValue());
Output:
18014398509481985 -> 1.8014398509481984E16
18014398509481986 -> 1.8014398509481984E16
true
Note the Exponent beeing increased from 15 to 16, which will cut off the difference of "1" between both longs.
To solve this, you can compare left1 to left2 and right1 to right2 without converting it to a double.
Your equal method should ideally test every necessary value in your class. In this case, it should be checking to see if your left and right values are the same between the two objects. If they are the same, then you can consider the objects to be equal.
In your case, you should probably put a debug point in your equals method to see why the function is returning back a false.
Try using Eclipse's built in functionality to create equals and hashcode methods for you. You can create that by going to Source->Generate hashCode() and equals(). The methods will be very different from what you have created.
Another thing, in your AssertEquals method, make sure both the values passed in are of the same type. In your case, you're checking a Double with an ExactNumber object. They will definitely not be the same. You need to either
Change your Add method to return a ExactNumber object
Have a method in your ExactNumber class called getDouble() and use that as the second parameter instead.
Hope this helps.