How does this approximation of division using bit shift operations work? - java

In java.util.DualPivotQuicksort, the following line of code appears:
// Inexpensive approximation of length / 7
int seventh = (length >> 3) + (length >> 6) + 1;
The variable length is an int greater than or equal to 47.
I am familiar with how the signed right shift operator works. But I do not know why these particular operations result in an approximation of division by 7. Could someone explain please?

>> is bitshift. Every bit you shift right, in effect divides the number of 2.
Therefore, (length >> 3) is length/8 (rounded down), and (length >> 6) is length/64.
Take (length/8)+(length/64) is approximately length*(1/8+1/64) = length*0.140625 (approximately)
1/7 = 0.142857...
The +1 at the end can be split into +0.5 for each term, so that length/8 is rounded to nearest (instead of down), and length/64 is also rounded to nearest.
In general, you can easily approximate 1/y, where y = 2^n+-1 with a similar bit-shift approximation.
The infinite geometric series is:
1 + x + x^2 + x^3 + ... = 1 / (1 - x)
Multiplying by x:
x + x^2 + x^3 + ... = x/(1 - x)
And substituting x = 1/2^n
1/2^n + 1/2^2n + 1/2^3n + ... = (1/2^n) / (1 - 1/2^n)
1/2^n + 1/2^2n + 1/2^3n + ... = (1/2^n) / ((2^n - 1)/2^n)
1/2^n + 1/2^2n + 1/2^3n + ... = 1 / (2^n - 1)
This approximates y = 2^n - 1.
To approximate y = 2^n + 1, substitute x = -1/2^n instead.
- 1/2^n + 1/2^2n - 1/2^3n + ... = (-1/2^n) / (1 + 1/2^n)
1/2^n - 1/2^2n + 1/2^3n - ... = (1/2^n) / ((2^n + 1)/2^n)
1/2^n - 1/2^2n + 1/2^3n - ... = 1 / (2^n + 1)
Then just truncate the infinite series to the desired accuracy.

Set x = 1/8 in the well-known equality
1 + x + x^2 + x^3 + ... = 1 / (1 - x)
and simplify, to give
1/8 + 1/64 + 1/512 + ... = 1/7
Multiply both sides of this by length in your example, to give
length / 7 = length / 8 + length / 64 + length / 512 + ...
Note that this is "exact" division, not integer division - I'm writing mathematics, not Java code.
Then the approximation assumes that the third and subsequent terms will be too small to matter, and that on average one of length / 8 and length / 64 is likely to need rounding up, rather than rounding down. So, now using integer division, length / 7 = length / 8 + length / 64 + 1 is a very good approximation.
The expression you gave, using bitwise operators, is just an alternative way of writing this, provided length is positive.

To put a mathematical background to ronalchn's answer:
Since 7=8-1=8*(1-1/8), by the geometric series division by 7 is the same as multiplication by
1/7 = 1/8·(1+1/8+1/8²+1/8³+…) = 1/8+1/8²+1/8³+…
To do the same for the division by 5, one would use that 3·5=16-1 and thus
1/5 = 3/16·(1+1/16+1/16²+…)
which would invite a formula like
(3*n)<<4 + (3*n) << 8 + 1

Computing all values of
n/8 + n/64 - n/7
the error grows linearly, while staying negative.
The list below shows the first time a given error appears
n = 7 e = -1
n = 63 e = -2
n = 511 e = -3
n = 959 e = -4
n = 1407 e = -5
n = 1855 e = -6
n = 2303 e = -7
n = 2751 e = -8
n = 3199 e = -9
n = 3647 e = -10
n = 4095 e = -11
n = 4543 e = -12
n = 4991 e = -13
n = 5439 e = -14
n = 5887 e = -15
n = 6335 e = -16
n = 6783 e = -17
n = 7231 e = -18
n = 7679 e = -19
n = 8127 e = -20
n = 8575 e = -21
n = 9023 e = -22
n = 9471 e = -23
n = 9919 e = -24
...
The ratio obviously tends to 1/448 = 1/8 + 1/64 - 1/7.

Related

i cant understanding negative 2 and positive 2 x=-10 % 4; System.out.println("-10% 4 : "+x); //-2 [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
class Example {
public static void main(String args[]) {
int x;
x = -10 % 4;
System.out.println("-10% 4 : " + x); // -2 "explain this"
x = -10 % -4;
System.out.println("-10% -4 : " + x); // -2 "explain this"
x = 10 % -4;
System.out.println("-10% -4 : " + x); // 2 "explain this"
x = 10 % 4;
System.out.println(" 10% 4 : " + x); // 2 "explain this"
}
}
I cant understand how to come (2,-2) plz explain it...
I cant understand negative 2 and positive 2 as the result of
x = -10 % 4;
System.out.println("-10% 4 : " + x); // -2
The operator % divides the left side by the right side as / would do, but the result is the remainder of the division and not the result of the division itself.
See this example where your code was extended and slightly changed:
public static void main(String[] args) {
int x;
int y;
x = -10 % 4; // calculates the remainder of...
y = -10 / 4; // ... this calculation
System.out.println("-10 / 4 = " + y + ", remainder: " + x);
x = -10 % -4;
y = -10 /- 4;
System.out.println("-10 / -4 = " + y + ", remainder: " + x);
x = 10 % -4;
y = 10 / -4;
System.out.println(" 10 / -4 = " + y + ", remainder: " + x);
x = 10 % 4;
y = 10 / 4;
System.out.println(" 10 / 4 = " + y + ", remainder: " + x);
}
This outputs
-10 / 4 = -2, remainder: -2
-10 / -4 = 2, remainder: -2
10 / -4 = -2, remainder: 2
10 / 4 = 2, remainder: 2
Well in programming languages they do the following:
-10%-4 is -2
-5%2 is -1
5%-2 is 1
they look at the first thing (before the % sign) to determine the return value.
If it is negative, the answer is negative. If it is positive, the answer is positive.
What hasn't been addressed by the other answers (so far) is why -10 % 4 = -2 and 10 % -4 = 2 while -10 / 4 = -2 and 10 / -4 = -2.
In division, if both dividend and divisor have the same sign (+/-) the result is positive. If they have different sign (one is positive the other negative) the result is negative.
As we can see from the result of the %-operator, that rule does not apply here. But why?
The %-operator is actually the following:
a % b = a - (a / b) * b
a = -10
b = -4
then gives
-10 - (-10 / -4) * -4 = -10 - (2) * -4 = -10 - -8 = -10 + 8 = -2
And the other alternatives
a = 10
b = 4
10 - (10 / 4) * 4 = 10 - (2) * 4 = 10 - 8 = 2
a = -10
b = 4
-10 - (-10 / 4) * 4 = -10 - (-2) * 4 = -10 - -8 = -10 + 8 = -2
a = 10
b = -4
10 - (10 / -4) * -4 = 10 - (-2) * -4 = 10 - 8 = 2

get dynamic ration for distrubution prize java

I have this algorithm that works, but I want to change it to have a dynamic ratio in order to have the distance of values for the first positions higher than those ones for the lastest positions.
So for instance if prize money = 1000, total_prizes = 5, last_prize = 50 I got:
1) 350.00
2) 275.00
3) 200.00
4) 125.00
5) 50.00
TOTAL SUM: 1000.00
What I would like to see should be:
1) 475.00
2) 250.00
3) 150.00
4) 75.00
5) 50.00
TOTAL SUM: 1000.00
Instead of having between positions always a fixed value of 75. Have an increase distance approaching the first positions, in this case
from 5) to 4) 25
from 4) to 3) 75
from 3) to 2) 100
from 2) to 1) 225
Here the current code:
public static void main(String[] aa){
float ratio;
float first_prize;
float s=0;
float money = 1000;
int total_prizes = 5;
float last_prize = 50;
float prizes[] = new float[total_prizes+1];
first_prize=2*(money/total_prizes)-last_prize; //last member of the progresion
ratio=(first_prize-last_prize)/(total_prizes-1);
prizes[total_prizes]=last_prize;
for (int j = total_prizes-1; j >=1; j--) {
prizes[j]=prizes[j+1]+ratio;
}
for(int k=1;k<=total_prizes;k++){
System.out.printf("%d) %.2f\n",k,prizes[k]);
s+=prizes[k];
}
System.out.printf("TOTAL SUM: %.2f\n",s);
}
Inside the loop:
for (int j = total_prizes-1; j >=1; j--) {
//ratio here should be calculated dynamically based on position...
prizes[j]=prizes[j+1]+ratio;
}
Thanks! :)
If I understand you, what you want is to have the following conditions:
Fixed total sum. In this case 1000.
Approximately a geometric ratio r with n terms. In this case 1.75.
All "round" numbers. In this case to the nearest 25.
I would suggest that you solve it by first creating an exact geometric sequence, and then tweak it to be round numbers.
The first step is easy because all geometric series with n terms look like this:
x + r * x + r^2 * x + ... + r^(n-1) * x
= x * (1 + r + r^2 + ... + r^(n-1))
= x * (1 + r + r^2 + ... + r^(n-1)) * (r - 1) / (r - 1)
= x * ((r - 1) + (r^2 - r) + (r^3 - r^2) + ... + (r^(n) - r^(n-1)) / (r - 1)
= x * (-1 + (r - r) + (r^2 - r^2) + ... + (r^(n-1) - r^(n-1)) + r^n) / (r - 1)
= x * (r^n - 1) / (r - 1)
So in we want
1000 = x * (r^n - 1) / (r - 1)
= x * (1.75^5 - 1) / (1.75 - 1)
= x * (16.4130859375 - 1) / 0.75
= 20.55078125 x
That gives us the following starting solution.
48.6599505797377
85.154913514541
149.021098650447
260.786922638282
456.377114616993
After that it is a question of tweaking those numbers up and down to get the answer that you want. There are a lot of ways you can do that. One is simply to start with the smallest and move it to a rounded number, and redistribute among the others in proportion to their weights, and continue. That gives you the following sequence of partial answers.
48.6599505797377
85.154913514541
149.021098650447
260.786922638282
456.377114616993
50
85.034965034965
148.811188811189
260.41958041958
455.734265734266
50
75
150.537634408602
263.440860215054
461.021505376344
50
75
150
263.636363636364
461.363636363636
50
75
150
275
450
This is not exactly your desired answer. But it is pretty darned close and hopefully acceptable as a strategy.
UPDATE I had tried 1.75 because it was close to (475/50)^(1/4). When I tried 1.8 instead I got your exact desired answer.
Furthermore note that we do not need to produce all of those intermediate answers. Each time we only need the smallest term. Which is given by target * (r-1) / (r^n - 1). Every time you find the smallest term, you subtract that from the target, reduce n by one, and repeat.

Given a singly linked list how to find the mod of it with a number

Given a decimal number represented as list from least significant bit to most significant bit how should one find mod with k if the list were a number.
Example :- number - 1234567
list representation of number: 7->6->5->4->3->2->1
k = 7
ans = 1234567%7 = 5
In python and java I could have converted the list to a number BigInteger(java) and have taken the mod. But I wanted to do it without using BigInteger.
I have tried calculating the mod while iterating the list
total=0
for digit in numberList:
total = (total * 10 + digit) % k
return total
But this is not going to work.
You can calculate the remainder of the i'th digit multiplied by 10^i for each digit. Then sum all these remainders and find the remainder of the sum :
int mul = 1;
int remainder = 0;
for (int digit : digitArray)
{
remainder += (digit * mul) % k;
mul *= 10;
}
remainder = remainder % k;
For 1234567%7, this loop basically computes :
(7 % 7 + 60 % 7 + 500 % 7 + 4000 % 7 + 30000 % 7 + 200000 % 7 + 1000000 % 7) % 7 =
(0 + 4 + 3 + 3 + 5 + 3 + 1) % 7 = 19 % 7 = 5
Your code is close, but you need to process your number list in reverse. I'll illustrate with a simple Python list.
num = 1234567
# Construct numberList
numberList = []
n = num
while n:
n, d = divmod(n, 10)
numberList.append(d)
k = 7
print(num, numberList, num % k)
# Find numberList mod k
r = 0
for d in reversed(numberList):
r = (10 * r + d) % k
print(r)
output
1234567 [7, 6, 5, 4, 3, 2, 1] 5
5
Think of the basic property of modular arithmetic :
(a*b)%m=(a%m * b%m ) % m
(a+b)%m=(a%m + b%m ) % m
Now, to find modulo of 1234567
1234567 % m = (1234 * 1000 + 567)%m
=((1234 * 1000)%m + 567%m) %m
Now, take a little small no. to better understand this trick
12345 =( ( (1 * 10 + 2) * 10 + 3) * 10 + 4) *10 +5
Now,
12345 % m = (((((((1*10)%m + 2)*10)%m + 3)*10)%m + 4)*10 + 5)%m
Now to find modulo of a number that is represented by a linked list its actually easy
list1: 1->2->3->4->5.......
take variable result and initialize with 0
i.e., result=0 and just traverse the list and do:
result = (result*10 )% m + node->data
see the code below it is too simple
int result=0;
while(list1){
int x=list1->data;
result=(result*10)%m + x;
list1=list1->next;
}
result=result%m;
return result;

Efficient solution for my task needed

I just solve this but want know more efficient way to do matrix multiplication
M = | 1 0 3 |
| 1 0 2 |
| 0 5 0 |
f[n] = M^n
I have implemented using Exponentiation_by_squaring
Is there more efficient then this ?
I guess, this is actually more suitable for math as there's a closed form solution. It's system of Linear homogeneous recurrence relations with constant coefficients.
Another posibility: You could speed up the program twice by deriving a formula for two steps, i.e., express RR(i) etc. via RR(i-2), etc.
And this can be repeated, so you can jump much faster.
One problem is that your calculations are overflowing. If you run it for K=1 and J=9, you get -334328541#510576792#-817751931.
The easiest fix for that is to do % 1000000006 in calculateProduction.
About efficiency, I would look at this problem as performing matrix multiplications.
You start with the vector (i.e. 1*3 matrix):
3 1 0
And at each step you multiply it (mod 1000000006) with the matrix:
1 1 0
0 0 5
3 2 0
Let's call the vector V and the matrix M. Basically you need to calculate V*MN. Since matrix multiplication is associative, you can calculate MN first, and do that recursively:
MN = (MN/2)2 if N is even, or
MN = M*(M[N/2])2 if N is odd
You don't need to calculate MM. This is why:
PP[i] = 5*MM[i-1] = 5*(RR[i-2] + 2*PP[i-2])
RR[i] = RR[i-1] + 3*PP[i-1] = (RR[i-2] + 3*PP[i-2]) + 3*PP[i-1]
See? You don't need to calculate MM at each step. This should be the algorithm:
public class RecurrenceMachine {
private static final int max = 1000000006;
public String calculate(int k, int j) {
long n = k * j;
if (n < 1)
return "error";
long RRi2 = 3;
long PPi2 = 0;
long RRi1 = 3 + 3 * PPi2;
long PPi1 = 5 * 1;
if (n == 1)
return RRi1 + "##" + (RRi2 + 2 * PPi2) + "##" + PPi1;
Long PPi = (long) 0, RRi = (long) 0, temp;
int i;
for (i = 2; i <= n; i++) {
temp = RRi2 + 2 * PPi2;
PPi = 5 * temp;
if (PPi >= max)
PPi %= max;
RRi = temp + PPi2 + 3 * PPi1;
if (RRi >= max)
RRi %= max;
RRi2 = RRi1;
PPi2 = PPi1;
RRi1 = RRi;
PPi1 = PPi;
}
return RRi + "##" + (RRi2 + 2 * PPi2) % max + "##" + PPi1;
}
}
I tried only with small values and it seems to work.

AVL Tree max and min node

how do i get the max and min number of nodes in an AVL tree when given the height of 8.
i can't seem to be able to trace it out properly from the formula f(8)=f(7)+f(6)+1
2*f(6)+f(5)+2
2*[f(5)+f(4)+1]+f(5)+2
3*f(5)+2*f4+4
3*[f(4)+f(3)+1]+2*f(4)+4
5*f(4)+3*f(3)+7
5*[f(3)+f(2)+1]+3*f(3)+7
8*f(3)+5*f(2)+12
8*[f(2)+f(1)+1]+5*f(2)+12
13*f(2)+8*f(1)+20
13*[f(1)+f(0)+1]+8*f(1)+20
21*f(1)+13*f(0)+33=54 whereas answer is 88 is the minimum
For every node in AVL tree we know that the depths of the left and the right subtree differs by at most 1 (this is given by definition).
From that, the next step is quite obvious : we take the minimum trees of depths N and N - 1 and place them as subtrees for a new root. It's clear that the AVL rules still hold and that the tree is contains as little nodes as possible (obvious from the induction base case).
From that, we've got the recursion formula : minnodes(depth) = 1 + minnodes(depth-1) + minnodes(depth - 2). That's a simple recursive equation, Wolfram Alpha can solve that for you (link).
The second case is trivial - a perfect binary tree of depth h contains as many nodes as possible for the depth given and trivially satisfies the AVL conditions.
You miscalculated a step somewhere, looks like near the end:
f(0) = 1
f(1) = 2
f(2) = f(1) + f(0) + 1 = 4
f(3) = f(2) + f(1) + 1 = 4 + 2 + 1 = 7
f(4) = f(3) + f(2) + 1 = 7 + 4 + 1 = 12
f(5) = f(4) + f(3) + 1 = 12 + 7 + 1 = 20
f(6) = f(5) + f(4) + 1 = 20 + 12 + 1 = 34
f(7) = f(6) + f(5) + 1 = 34 + 20 + 1 = 55
f(8) = f(7) + f(6) + 1 = 55 + 34 + 1 = 88
And if you don't believe it, you can always cook up a quick snippet to check:
#Test
public void testGetMax() {
assertEquals(88, getMax(8));
}
int getMax(int x) {
switch (x) {
case 0:
return 1;
case 1:
return 2;
default:
return getMax(x - 1) + getMax(x - 2) + 1;
}
}

Categories

Resources