Implement Generic Power Function Without Using Math.pow in Java - java

I want to write a program in java, which will perform a number raised to a power, but without using math.pow. The program should be generic to include fractions as well.
The loop increment method will increment by 1, which is okay for integers; but not fractions. Please Suggest a generic method that would be helpful to me.

First, observe that pow(a,x) = exp(x * log(a)).
You can implement your own exp() function using the Taylor series expansion for
ex:
ex = 1 + x + x2/2! + x3/3! + x4/4! + x5/5! + ...
This will work for non-integer values of x. The more terms you include, the more
accurate the result will be.
Note that by using some algebraic identities, you only need to resort to the series expansion for x in the range 0 < x < 1 . exp(int + frac) = exp(int)*exp(frac), and there's no need to use a series expansion for exp(int). (You just multiply it out,
since it's an integer power of e=2.71828...).
Similarly, you can implement log(x) using one of these series expansions:
log(1+x) = x - x2/2 + x3/3 - x4/4 + ...
or
log(1-x) = -1 * (x + x2/2 + x3/3 + x4/4 + ... )
But these series only converge for x in the interval -1 < x < 1. So for values
of a outside this range, you might have to use the identity
log(pq) = log(p) + log(q)
and do some repeated divisions by e (= 2.71828...) to bring a down into a range where
the series expansion converges. For example, if a=4, you'd have to take take x=3
to use the first formula, but 3 is outside the range of convergence. So we start
dividing out factors of e:
4/e = 1.47151...
log(4) = log(e*1.47151...) = 1 + log(1.47151...)
Now we can take x=.47151..., which is within the range of convergence, and evaluate log(1+x) using the series expansion.

Think about what a power function should do.
Mathematically: x^5 = x * x * x * x * x, or ((((x*x)*x)*x)*x)
Within your for loop, you can use the *= operator to achieve the operation that happens above.
How are you handling fractions? Java has no built-in fraction type; it stores decimals that would calculate the same way as integers (in other words, x * x works with both types). If you have a special class for fractions, your loop just needs two steps: one to multiply the numerator and one to multiply the denominator.

While reading up on powers on Wikipedia:
a^x = exp( x ln(a) ) for any real number x
Is this cheating?

Related

Distribute given number in a greedy manner

I am hitting a wall in coming up with an equation to this simple question. I need a different perspective coming up with an algorithm. I have a number x and I want to distribute it to n elements in a greedy manner.
For x=9, n=3
[1,2,3],[4,5,6],[7,8,9] OR [3,3,3]
For x=10, n=3
[1,2,3,4],[5,6,7],[8,9,10] OR [4,3,3]
For x=11, n=3
[1,2,3,4],[5,6,7,8],[9,10,11] OR [4,4,3]
For x=12, n=3
[1,2,3,4],[5,6,7,8],[9,10,11,12] OR [4,4,4]
As far as I understand, you need to get array like [4,4,3]. So use integer division and modulo operation
smallvalue = x / n ; //integer division
largecount = x % n; //number of larger values
smallcount = n - largecount
Now fill array with largecount quantity of smallvalue+1 and then with smallcount of smallvalue
If you need result [1,2,3,4],[5,6,7,8],[9,10,11] - use the same information to generate it.

Generating random integer between 1 and infinity

I would like to create an integer value between 1 and infinity. I want to have a probability distribution where the smaller the number is, the higher the chance it is generated.
I generate a random value R between 0 and 2.
Take the series
I want to know the smallest m with which my sum is bigger than R.
I need a fast way to determine m. This is would be pretty straightforward if i had R in binary, since m would be equal to the number of 1's my number has in a row from the most significant bit, plus one.
There is an upper limit on the integer this method can generate: integer values have an upper limit and double precision can also only reach so high in the [0;2[ interval. This is irrelevant, however, since it depends on the accuracy of the data representation method.
What would be the fastest way to determine m?
Set up the inequality
R <= 2 - 2**-m
Isolate the term with m
2**-m <= 2 - R
-m <= log2(2-R)
m >= -log2(2-R).
So it looks like you want ceiling(-log2(2-R)). This is basically an exponential distribution with discretization -- the algorithm for an exponential is -ln(1-U)/rate, where U is a Uniform(0,1) and 1/rate is the desired mean.
I think, straightforward solution will be OK as this series converges really fast:
if (r >= 2)
throw new IllegalArgumentException();
double exp2M = 1 / (2 - r);
int x = (int)exp2M;
int ans = 0;
while (x > 0) {
++ans;
x >>= 2;
}
return ans;

Summation equation in Java?

I would like to know how I would go about writing this summation equation in java. But, the trick is, I need the summation to be equal to an amount.
x= Total Loss Streak amount
sb= Starting Bet
m= multiplier
The whole equation will equal to the current amount of currency in one's account. The amount of times the summation can complete itself while adding up needs to be less than or equal to the amount of currency in ones account.
Fyi, this is for a dicebot that work's on peerbet.org and I want to be able to show the user how many times he can loose in a row without wasting all his money.
If this question is bad, please do not answer it and let me delete it. Also, it thought the middle part was code, so I had to put it as such or it wouldn't let me post.
Renaming sb to just b. This is just a sum of a geometric progression
In Java, you can write:
return b * (m * m - Math.pow(m, x + 1)) / (1 - m);
This will be considerably faster than using a loop, although you must check that m is not 1.
If you want to solve for x given a sum S then a rearrangement of the formula gives the following Java code:
double x = Math.log(m * m - S * (1 - m) / b) / log(m) - 1;
and truncate this result to get the integral value of x where the next integer bankrupts the player.
EDIT: apparently we are solving for x. still easily doable with a loop.
int sum = 0;
int x =2;
while(sum<=amount){
sum+=sb*(Math.pow(m,x));
}
return x;
A summation is really just an adding for loop right?
int sum = 0;
for(int i=2; i<x; i++){
sum+=sb*(Math.pow(m,i));
}
return sum;
I'm not entirely clear I'm reading your formula correctly: are you summing up integers from 2 to x on the left-hand side of the equals sign, and you want that sum to be equal to the term on the right-hand side?
In that case, we could do the following transformation:
(Note that the first step might not be what you had in mind.)
We can now easily solve this using the quadratic formula to get:
Assuming that we're calculating in the reals, note that the root is only defined for non-negative arguments. The result of taking that root yields a non-negative number and substracting that non-negative number from -1 would give something <= -1, i.e., a negative number. Dividing it by 2 won't make it positive, either, but we've assumed from the get-go that our x must be >= 2, or else the very first sum wouldn't make any sense.
Therefore we can disregard the - case of the +/- in the formula altogether. Hence:
This should be straight-forward to translate into Java code, but note that the result is likely not to be an integer, so you will have to round if you're looking for an upper bound.

Find a sum equal or greater than given target using only numbers from set

Example 1:
Shop selling beer, available packages are 6 and 10 units per package. Customer inputs 26 and algorithm replies 26, because 26 = 10 + 10 + 6.
Example 2:
Selling spices, available packages are 0.6, 1.5 and 3. Target value = 5. Algorithm returns value 5.1, because it is the nearest greater number than target possible to achieve with packages (3, 1.5, 0.6).
I need a Java method that will suggest that number.
Simmilar algorithm is described in Bin packing problem, but it doesn't suit me.
I tried it and when it returned me the number smaller than target I was runnig it once again with increased target number. But it is not efficient when number of packages is huge.
I need almost the same algorithm, but with the equal or greater nearest number.
Similar question: Find if a number is a possible sum of two or more numbers in a given set - python.
First let's reduce this problem to integers rather than real numbers, otherwise we won't get a fast optimal algorithm out of this. For example, let's multiply all numbers by 100 and then just round it to the next integer. So say we have item sizes x1, ..., xn and target size Y. We want to minimize the value
k1 x1 + ... + kn xn - Y
under the conditions
(1) ki is a non-positive integer for all n ≥ i ≥ 1
(2) k1 x1 + ... + kn xn - Y ≥ 0
One simple algorithm for this would be to ask a series of questions like
Can we achieve k1 x1 + ... + kn xn = Y + 0?
Can we achieve k1 x1 + ... + kn xn = Y + 1?
Can we achieve k1 x1 + ... + kn xn = Y + z?
etc. with increasing z
until we get the answer "Yes". All of these problems are instances of the Knapsack problem with the weights set equal to the values of the items. The good news is that we can solve all those at once, if we can establish an upper bound for z. It's easy to show that there is a solution with z ≤ Y, unless all the xi are larger than Y, in which case the solution is just to pick the smallest xi.
So let's use the pseudopolynomial dynamic programming approach to solve Knapsack: Let f(i,j) be 1 iif we can reach total item size j with the first i items (x1, ..., xi). We have the recurrence
f(0,0) = 1
f(0,j) = 0 for all j > 0
f(i,j) = f(i - 1, j) or f(i - 1, j - x_i) or f(i - 1, j - 2 * x_i) ...
We can solve this DP array in O(n * Y) time and O(Y) space. The result will be the first j ≥ Y with f(n, j) = 1.
There are a few technical details that are left as an exercise to the reader:
How to implement this in Java
How to reconstruct the solution if needed. This can be done in O(n) time using the DP array (but then we need O(n * Y) space to remember the whole thing).
You want to solve the integer programming problem min(ct) s.t. ct >= T, c >= 0 where T is your target weight, and c is a non-negative integer vector specifying how much of each package to purchase, and t is the vector specifying the weight of each package. You can either solve this with dynamic programming as pointed out by another answer, or, if your weights and target weight are too large then you can use general integer programming solvers, which have been highly optimized over the years to give good speed performance in practice.

Generating the list of random numbers with certain average difference

I have to generate a list of random numbers and they have to have a given average difference. For example, a given average difference is 10, so these numbers are good: 1 3 5 9 15 51. What I do, is multiply the given average difference by 2 and add 1. Like this:
while (i <= 50000)
{
i += Math.random() * givenAverageDiff * 2 + 1;
list.add(i);
}
But I never get 5000 or more. In fact, it's always 4,850 or less. Why? Let's say givenAverageDiff is 10. What's my mistake? How can I fix it?
P.S. Implementation in C or PHP is also good for me.
Because you are doing "+ 1".
Let us calculate the expected difference:
E(2*10*x+1)= 2*10*E(x)+1 = 2*10*0.5+1 = 10+1. So, on an average you will get 50000/11 numbers.
You need to pick something whose expected value is equal to 10. Change it to the following and it should work:
while (i <= 50000)
{
i += Math.random() * (givenAverageDiff-1) * 2 + 1;
list.add(i);
}
Think about it in terms of the ranges you create. With your current calculation,
i += Math.random() * givenAverageDiff * 2 + 1;
you are adding between 1 and 2*givenAverageDiff to your number. The sum of 1 through 2x is (2x)(2x+1)/2, and since there are 2x options we divide by 2x to get (2x)(2x+1)/(2*2x) = (2x+1)/2 = x + 0.5.
So what you want is to have 2x+1 options, which is easiest by using a range of [0,2*x]. You can get that by adding parenthesis:
i += Math.random() * (givenAverageDiff * 2 + 1);
If you want it to always increase, then you either need use a non-uniform distribution, or a uniform distribution with a smaller range. To get a range [n,2*x-n] use
i += Math.random() * ((givenAverageDiff - n) * 2 + 1) + n;
If you use a negative value for n you can widen the range, making it possible for numbers to decrease as well.

Categories