Is there a java version of matlab's colon operator or linspace? For instance, I'd like to make a for loop for evenly spaced numbers, but I don't want to bother with creating an array of those numbers manually.
For example to get all integers from 1 to 30, in matlab I would type:
1:30
or
linspace(1,30)
For the two variable call, #x4u is correct. The three variable call will be quite a bit harder to emulate.
For instance, i think that linspace(1,30,60) should produce values 1, 1.5, 2, 2.5, 3, 3.5..., or maybe that's the values for linspace(1,30,59)--either way, same problem.
With this format you'll have to do the calculations yourself--Personally I'd create a new object to do the whole thing for me and forget the for loop.
counter=new Linspace(1,30,60);
while(counter.hasNext()) {
process(counter.getNextFloat())
}
or simply
while(float f : new Linspace(1,30,60)) {
process(f);
}
if you have your Linspace object implement Iterable.
Then the inside of the counter object should be pretty obvious to implement and it will easily communicate to you what it is doing without obfuscating your code with a bunch of numeric calculations to figure out ratios.
An implementation might be something like this:
(NOTE: Untested and I'm pretty sure this would be vulnerable to edge cases and floating point errors! It also probably won't handle end < start for backwards counting, it's just a suggestion to get you going.)
public class Linspace {
private float current;
private final float end;
private final float step;
public Linspace(float start, float end, float totalCount) {
this.current=start;
this.end=end;
this.step=(end - start) / totalCount;
}
public boolean hasNext() {
return current < (end + step/2); //MAY stop floating point error
}
public float getNextFloat() {
current+=step;
return current;
}
}
Do you want to do this?
for( int number = 1; number <= 30; ++number )
If you need them spaced by a fixed amount, i.e. 3 you can write it this way:
for( int number = 1; number <= 30; number += 3 )
The left part of the for loop initializes the variable, the middle part is the condition that gets evaluated before each iteration and the right part gets executed after each iteration.
I actually just had to do this for a java project I am working on. I wanted to make sure it was implemented in the same way as in MATLAB, so I first wrote a MATLAB equivalent:
function result = mylinspace(min, max, points)
answer = zeros(1,points);
for i = 1:points
answer(i) = min + (i-1) * (max - min) / (points - 1);
end
result = answer;
I tested this against the built-in linspace function and it returned the correct result, so I then converted this to a static java function:
public static double[] linspace(double min, double max, int points) {
double[] d = new double[points];
for (int i = 0; i < points; i++){
d[i] = min + i * (max - min) / (points - 1);
}
return d;
}
In my opinion this is much simpler than creating a new class for this one function.
I think Bill K got the right idea, but I think there is no need to have a Linspace class.
// If you write linspace(start,end,totalCount) in Matlab ===>
for(float i = start; i < end; i += (end-start)/totalCount)
something(i);
I was myself looking for a solution for this problem and investigated how MatLab implements its Linspace. I more or less converted it to Java and ended up with the method below. As far as I have tested it works quite nicely and you get the endpoints. There is probably floating point errors as with most cases.
I am not sure if there are Copyright issues with this though.
public static List<Double> linspace(double start, double stop, int n)
{
List<Double> result = new ArrayList<Double>();
double step = (stop-start)/(n-1);
for(int i = 0; i <= n-2; i++)
{
result.add(start + (i * step));
}
result.add(stop);
return result;
}
If you'd like to use Java Streams, one option would be:
public static Stream<Double> linspace(double start, double end, int numPoints) {
return IntStream.range(0, numPoints)
.boxed()
.map(i -> start + i * (end - start) / (numPoints - 1));
}
Here's the main algo that works for matlab, you may convert this to Java with all the OOP details at your disposal:
>>> st=3;ed=9;num=4;
>>> linspace(st,ed,num)
ans =
3 5 7 9
>>> % # additional points to create (other than 3)
>>> p2c=num-1;
>>> % 3 is excluded when calculating distance d.
>>> a=st;
>>> d=ed-st;
>>> % the increment shall calculate without taking the starting value into consideration.
>>> icc=d/p2c;
>>> for idx=[1:p2c];
a(idx+1)=a(idx)+icc;
end;
>>> a
a =
3 5 7 9
>>> diary off
Related
I am trying to solve a problem on leetcode.com Ugly Number II.
problem: An ugly number is a positive integer whose prime factors are limited to 2, 3, and 5.
Given an integer n, return the nth ugly number.
example:
Input: n = 10
Output: 12
Explanation: [1, 2, 3, 4, 5, 6, 8, 9, 10, 12] is the sequence of the first 10 ugly numbers.
This is my solution
class Solution {
public int nthUglyNumber(int n) {
int outputNumber = 6;
int temp = 1;
if (n < 7) {
return n;
}
int i = 7;
while (i != (n + 1)) {
outputNumber = outputNumber + 1;
temp = outputNumber;
while (temp % 5 == 0) {
temp = temp / 5;
}
while (temp % 2 == 0) {
temp = temp / 2;
}
while (temp % 3 == 0) {
temp = temp / 3;
}
if (temp == 1) {
i = i + 1;
}
}
return outputNumber;
}
}
this works for small numbers, but when the input is a big number, then I have Time Limit Exceeded
The question is how to optimize this code?
Thank you!
Hint: You're looking for numbers of the form 2a×3b×5c for non-negative integers a, b, c. Instead of looking for ugly numbers, wouldn't it be easier to just generate them?
I used two tricks to make it about twice as fast, but it's still far too slow. I suspect the check-all-integers-for-ugliness approach is hopeless, and you'll find faster approaches in the discussions on LeetCode.
class Solution {
public int nthUglyNumber(int n) {
for (int i = 1; true; i++)
if (1418776204833984375L % (i / (i & -i)) == 0)
if (--n == 0)
return i;
}
}
The two tricks:
i & -i extracts the lowest 1-bit, so dividing by that takes out every factor 2.
1418776204833984375 is 319×513. Every positive int with only factors 3 and 5 divides that, and every other positive int doesn't.
I think the easiest way is to just maintain a collection of ugly numbers that we will need to visit. We start with a collection containing just 1, and then at each step, we remove the lowest value, and add the values found by multiplying our lowest value by 2, by 3, and by 5. Since these may be duplicates (24 = 8 * 3 and 24 = 12 * 2) but we only want them once apiece, our collection should be a Set.
My Java is far too rusty, but here's a JavaScript implementation that you could use as pseudocode:
const ugly = (count) => {
const upcoming = new Set ([1])
const found = []
while (found .length < count) {
const next = Math .min (...upcoming .values ())
found .push (next)
upcoming .delete (next)
upcoming .add (2 * next)
upcoming .add (3 * next)
upcoming .add (5 * next)
}
return found
}
const uglies = ugly (1690) // This was the upper bound specified in the problem
const nthUglyNumber = (n) => uglies [n - 1]
console .log (nthUglyNumber (10))
console .log (nthUglyNumber (1690))
ugly finds the first count ugly numbers, returning them as an Array. Internally, it keeps two collections. upcoming is the ugly numbers we know we would eventually hit. found is an array of numbers we have actually reached, always taking the smallest of the upcoming values. When we select the next one, we remove it from upcoming and add to upcoming its 2-, 3-, and 5-multiples.
This could be modified to be our only function. But it's nice to call it once for our top value, and store the resulting array, as uglies. Then nthUglyNumber is a simple function that extracts the value at the correct index.
This is the first, inefficient method I wrote:
public int sumOfMultiplesOf3or5Under1000() {
int sum = 0;
for (int i = 0; i < 1000; i++) {
if (i % 3 == 0 || i % 5 == 0) {
sum += i;
}
}
return sum;
}
Here is my attempt at coding a more efficient solution using the arithemtic progression formula:
public int usingAP() {
return sumOfAP(3,3,333) + sumOfAP(5,5,199) - sumOfAP(15,15,66);
}
public int sumOfAP(int firstTerm, int commonDifference, int numberOfTerms){
int sum = (numberOfTerms / 2) * (2 * firstTerm + (numberOfTerms -
1) * commonDifference);
return sum;
}
When I call sumOfMultiplesOf3or5Under1000() I get the correct answer:
233168
When I call usingAP() I get an answer that's off by just 1,001:
232167
I'm not sure why you consider your first method to be inefficient for the reason that I stated in the comment above. Nevertheless, it seems you fell victim to rounding errors in your sumOfAP method. You were close, but you just need some way to store the temporary variables as double instead of int so you can retain the precision. I was able to fix it by dividing and multiplying by 2D instead of 2:
public static int sumOfAP(int firstTerm, int commonDifference, int numberOfTerms){
return (int) ((numberOfTerms / 2D) * (2D * firstTerm + (numberOfTerms - 1) * commonDifference));
}
You can run the following and verify that they're equivalent:
System.out.println(usingAP());
System.out.println(sumOfMultiplesOf3or5Under1000());
Output:
233168
233168
I have a start and end point, I'd like to loop through them using a specific step size, but I need to ensure that the end point is included. Is the following the best way to accomplish this, or is there a better way?
Double start = 2.1;
Double end = 5.3;
Double step = 0.6;
for(Double i = start; i <= end; i += step) {
// do stuff
if(i != end && (i + step) > end) {
i = end;
}
}
You can use an instruction outside the loop , to do the end part.
Don't use double in iterations. Because of the way floating point numbers are stored, you may 2.1 +0.6 as 2.7 but as 2.69999999999999999999 for example. In this case, multiply by 10 to achieve what you want.
Your solution is wrong. You make i=end, but it is then added by step, so you dont iterate. You could use:
if(i != end && (i + step) > end) {
i = end-step;
}
Generally you should prefer integers for your loop variables, especially when the interval divides in the whole number of steps. In case this is not possible you could use double values, but you need to be careful to avoid precision pitfalls of double computations.
Comparing doubles for equality is not a good idea. A better approach is to use Math.min to cap i at the value of end:
for(double i = start; i < end+step; i += step) {
double pt = Math.min(end, i);
... // use pt here
}
You can calculate the number of integer steps required and use these to control the loop. When you reach the final step you use the end value.
public static void main(String[] args)
{
Double start = 2.1;
Double end = 5.3;
Double step = 0.6;
int steps = (int)Math.round((end-start)/step);
if(start + steps*step < end) steps++;
double pos = start;
for(int s=0; s<=steps; )
{
System.out.println(pos);
s += 1;
pos = (s==steps) ? end : start + step*s;
}
}
Output:
2.1
2.7
3.3
3.9
4.5
5.1
5.3
Note that for the intermediate steps we calculate the position using a multiplication rather than repeated addition. I can't find a reference at the moment but my understanding is that this incurs less floating point "drift". This seems to be borne out. If we use:
pos = (s==steps) ? end : pos+step;
to calculate the next pos then we get as output:
2.1
2.7
3.3000000000000003
3.9000000000000004
4.5
5.1
5.3
I am trying to better understand recursion. I am writing a basic geometric series method which I know could be done easier with a loop but that is not the purpose. The method is producing the currect output for the values of 0 and 1 which is simply 1 and 1.5. But for 2 it is outputting 1.25 when it should be 1.75. Any pointers on a better way to approach this?
public static double geometricSum(int n) {
if(n == 0){
return 1;
}
n = n * 2;
return 1.0 / n + geometricSum((int) (1/Math.pow(2, n)));
}
This happens because you are casting a float into a int.
1/(2^2)=1/4=0.25 --> 0
As you are passing your float as an int you're not getting your thing working propperly.
So 0.25 + geometricSum(0)=1.25.
On the first one happens the same. you pass the 0.5, but turned into an int so you.re not getting your aproximation propperly done.
As an advice, ALWAYS put () on your math functions in order to make the program, and you yourself, understand in which order it computes the numbers.
The first problem is the cast to int, giving the wrong result, already described by reyeselda95.
There is a second problem hidden, which is that if you fix that you get this:
public static double geometricSum(double n) {
System.err.println("Calling with " + n);
if(n == 0){
return 1;
}
n = n * 2;
return 1.0 / n + geometricSum((1/Math.pow(2, n)));
}
Calling this with the provided value of 2, leads to a loop between calls with the following values, leading to a stack overflow.
...
Calling with 0.4999999999999999
Calling with 0.5000000000000001
Calling with 0.4999999999999999
Calling with 0.5000000000000001
...
This may be the function you are looking for, if I understand correctly:
public static double geometricSum(int count) {
if (count == 0) {
return 1;
}
return geometricSum(count-1) + Math.pow(2, -count);
}
Don't cast float to int;
When using float, are you sure your formula is correct? The recursion breaks if an argument is zero, but you will get StackOverflowError when passing the result of 1.0/Math.pow(2, n) to the function.
This is my python code:
def geometricSum(k):
if k == 0:
return 1
return 1/2**k + geometricSum(k-1)
k = int(input())
print(geometricSum(k))
This is all about the power of 2 i.e. 2 Pow n where n is an integer.
Here Recursion is used to get the sequence of values for n.
In my case I've to calculate the value for 1/(2 pow n).
I am using the "think java" book and I am stuck on exercise 7.6. The goal here is to write a function that can find . It gives you a couple hints:
One way to evaluate is
to use the infinite series expansion:
In other words, we need to add up a series of terms where the ith term
is equal to
Here is the code I came up with, but it is horribly wrong (when compared to Math.exp) for anything other than a power of 1. I don't understand why, as far as I can tell the code is correct with the formula from the book. I'm not sure if this is more of a math question or something related to how big of a number double and int can hold, but I am just trying to understand why this doesn't work.
public static void main(String[] args) {
System.out.println("Find exp(-x^2)");
double x = inDouble("Enter x: ");
System.out.println("myexp(" + -x*x + ") = " + gauss(x, 20));
System.out.println("Math.exp(" + -x*x + ") = " + Math.exp(-x*x));
}
public static double gauss(double x, int n) {
x = -x*x;
System.out.println(x);
double exp = 1;
double prevnum = 1;
int prevdenom = 1;
int i = 1;
while (i < n) {
exp = exp + (prevnum*x)/(prevdenom*i);
prevnum = prevnum*x;
prevdenom = prevdenom*i;
i++;
}
return exp;
} // I can't figure out why this is so inacurate, as far as I can tell the math is accurate to what the book says the formula is
public static double inDouble(String string) {
Scanner in = new Scanner (System.in);
System.out.print(string);
return in.nextDouble();
}
I am about to add to the comment on your question. I do this because I feel I have a slightly better implementation.
Your approach
Your approach is to have the function accept two arguments, where the second argument is the number of iterations. This isn't bad, but as #JamesKPolk pointed out, you might have to do some manual searching for an int (or long) that won't overflow
My approach
My approach would use something called the machine epsilon for a data type. The machine epsilon is the smallest number of that type (in your case, double) that is representable as that number. There exists algorithm for determining what that machine epsilon is, if you are not "allowed" to access machine epsilon in the Double class.
There is math behind this:
The series representation for your function is
Since it is alternating series, the error term is the absolute value of the first term you choose not to include (I leave the proof to you).
What this means is that we can have an error-based implementation that doesn't use iterations! The best part is that you could implement it for floats, and data types that are "more" than doubles! I present thus:
public static double gauss(double x)
{
x = -x*x;
double exp = 0, error = 1, numerator = 1, denominator = 1;
double machineEpsilon = 1.0;
// calculate machineEpsilon
while ((1.0 + 0.5 * machineEpsilon) != 1.0)
machineEpsilon = 0.5 * machineEpsilon;
int n = 0; //
// while the error is large enough to be representable in terms of the current data type
while ((error >= machineEpsilon) || (-error <= -machineEpsilon))
{
exp += error;
// calculate the numerator (it is 1 if we just start, but -x times its past value otherwise)
numerator = ((n == 0) ? 1 : -numerator * x);
// calculate the denominator (denominator gets multiplied by n)
denominator *= (n++);
// calculate error
error = numerator/denominator;
}
return exp;
}
Let me know how this works!