Mean of two ints (or longs) without overflow, truncating towards 0 - java

I'd like a way to calculate (x + y)/2 for any two integers x, y in Java. The naive way suffers from issues if x+y > Integer.MAX_VALUE, or < Integer.MIN_VALUE.
Guava IntMath uses this technique:
public static int mean(int x, int y) {
// Efficient method for computing the arithmetic mean.
// The alternative (x + y) / 2 fails for large values.
// The alternative (x + y) >>> 1 fails for negative values.
return (x & y) + ((x ^ y) >> 1);
}
... but this rounds towards negative infinity, meaning the routine doesn't agree with the naive way for values like {-1, -2} (giving -2, rather than -1).
Is there any corresponding routine which truncates towards 0?
"Just use long" is not the answer I'm looking for, since I want a method that works for long inputs too. BigInteger is also not the answer I'm looking for. I don't want a solution with any branches.

You need to add 1 to the result if the lowest bits are different (so the result is not exact and you need to round), and the sign bit in the result is set (the result is negative, so you want to change the round down into a round up).
So the following should do (untested):
public static int mean(int x, int y) {
int xor = x ^ y;
int roundedDown = (x & y) + (xor >> 1);
return roundedDown + (1 & xor & (roundedDown >>> 31));
}

Why don't you do something like (x-y)/2 + y, which reduces to x/2 - y/2 + y = x/2 + y/2? So if x+y gives you an overflow or underflow, you do it the (x-y)/2 + y way.

Related

Different implementations of compare method for Long, Integer and Short?

Why are the implementations of the static method compare for Long, Integer and Short in Java's library different?
For Long:
public static int compare(long x, long y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
For Integer:
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
For Short:
public static int compare(short x, short y) {
return x - y;
}
If you try:
System.out.println(Long.MIN_VALUE - Long.MAX_VALUE);
or
System.out.println(Integer.MIN_VALUE - Integer.MAX_VALUE);
You will get 1 because of overflow(update: should be underflow here, as mentioned in another answer), which is incorrect.
However, with
System.out.println(Short.MIN_VALUE - Short.MAX_VALUE);
you will get correct value -65535, because short will be converted to int before - operation, which prevents the overflow.
x - y is presumably the most efficient (since the alternative involves branching twice), so that's used for short.
But x - y can't be used for int or long, because this will overflow when the resulting value doesn't fit in an int, which can give a positive value when the result should be negative, or a negative value when the result should be positive (or zero in either case).
Note: when subtracting two shorts, the resulting value is of type int, so that can never overflow.
// long - long
System.out.println((int)(2147483649l - 1l)); // -2147483648, not 2147483648
// int - int
System.out.println(-2147483648 - 1); // 2147483647, not -2147483649
// int - int
System.out.println(1 - -2147483648); // -2147483647, not 2147483649
// short - short
short s1 = -32768, s2 = 1;
System.out.println(s1 - s2); // -32769, as desired
For what it's worth: the values above were chosen since they're roughly around the minimum and maximum values for int (and short), to demonstrate at which point it overflows.
int can have values between [-2147483648, +2147483647]. If you subtract -2147483648 from +2147483647, you will get 4294967295. This can't be stored in an int, therefore we use this for comparing 2 ints
return (x < y) ? -1 : ((x == y) ? 0 : 1);
The same is the case with long.

how to get value of three numbers knowing three information

I am trying to solve a problem that I need to get value of three unknowns(x,y,z) knowing some info. their summation is equal to 70, x^2 + y^2 = z^2 and x < y < z.
Answer should be x = 20, y = 21, z = 29
I tried to solve it as two equations in three unknowns but I failed. Any hints to get the solution ? I want to find an algorithm or equation to build a java code that solve this problem
I'll assume that x, y, and z must be positive integers, since removing the integers restriction allows infinitely many solutions. Here is an algorithm--I'll leave the code to you.
Your second equation x^2 + y^2 = z^2 means that x, y, and z form a Pythagorean triple. All solutions to that equation have the form
x = k(m^2 - n^2), y = 2kmn, z = k(m^2 + n^2)
(with possibly x and y swapped) where m, n, and k are positive integers, m > n, one of m and n is even and the other is odd, and (m, n) are relatively prime. You can drop those last two restrictions on m and n, which is to make the triples have unique representation.
Your third limitation x < y < z merely makes a unique triple from the three values. Importantly, your first restriction x + y + z = 70 means that your solution has "small" values.
So in your code, vary the three parameters k, m, and n. There are only finitely many values that allow the sum of x, y, and z to be less than or equal 70, which places limits on k, m, and n. Find the ones that equal make the sum of x, y, and z to be 70. You can cut the number of trials in half by not letting m and n be both even or both odd. You can also avoid explicitly varying k by varying only m and n and calculating what k should be, since each of x, y, z vary proportionally with k, and accept only integral k.
This is somewhat of a brute-force solution, but it is easy to program and will be faster than just trying all values of x, y, and z.
EDIT: I now see that x, y, and z may also be zero. That theoretically means that you need to test for x = 0, but that is clearly impossible here since then y^2 = z^2 which contradicts y < z. So no change is needed to my algorithm.
Expanding on #RoryDaulton's answer, taking x = k(m^2 - n^2), y = 2kmn and z = k(m^2 + n^2) and applying the sum constraint gives us
2*k*m*(m + n) = 70
Or
k * m * (m + n) = 35 = 7 * 5 = 35 * 1
The important thing to note is that the RHS of the above has only two unique factors; the LHS has three. Thus at least one factor of the LHS (k, m, m + n) must be 1.
Since m and n are unique positive integers, m + n will always be greater than 1. Thus,
k = 1 or m = 1
And the only possible values for the remaining LHS factors are 7 and 5 or 35 and 1.
This makes the problem much easier to brute force.
I have solved the question and I want to thank all people who helped me.
This is My code to solve the problem
int x,y,z;
long mul=0;
for(int n=1;n<=sum;n++){
for (int m=2;m<=sum;m++){
x= (int) ((Math.pow(m,2)) - (Math.pow(n,2)));
y= 2*m*n;
z= (int) ((Math.pow(m,2)) + (Math.pow(n,2)));
if(x+y+z == sum){
mul = x*z*y;
}
}}
return mul; }}

Selecting points such that sum of x coordinates = sum of y coordinates

I have an array of Points. I need to select a subset of points from it, such that the sum of x coordinates of the points = sum of y coordinates of the points.
If there are many such subsets, the one with largest sum of x coordinates is required.
The sum of x coordinates needs to be reported.
I have written a brute force recursive method, which tests all possibilities.
Point[] a = new Point[n];
// ...
private int rec(int i, int x, int y) {
if (i == n - 1) {
if (x + a[i].x == y + a[i].y) return x + a[i].x;
return (x == y) ? x : -1;
}
return Math.max(rec(i + 1, x, y), rec(i + 1, x + a[i].x, y + a[i].y));
}
The answer is rec(0, 0, 0).
My questions are:
1) Is there a dynamic programming solution for this?
2) If yes, could anyone please explain
I have a bit better (than brute force) algorithm.
Divided all coordinates into three sets: 1: {(x,y): x>y}, 2: {(x,y):x==y}, 3:{(x,y): x lower-than y}
Set 2 have to be always included in the solution.
for each (x,y) from 1 define net=x-y and for each (x,y) form 3 define net=y-x
check all possible values you can obtained from nets in 1 and nets in 3.
then basing on the greatest match it is easy to construct the solution.
Does it make sense?
For each point, set its value to x - y.
Now we need to find a set of points whose values sum to 0.
This is exactly the subset sum problem.
It is NP-complete (i.e. there is no known polynomial time algorithm for the generic case of the problem), but there exists a pseudo-polynomial time DP solution, which is given on Wikpedia, linked above. A brief summary:
We define a function Q(i,s) to be the value (true or false) of
there is a nonempty subset of x1, ..., xi which sums to s
Then we have the following recurrence:
Q(1,s) := (x1 == s)
Q(i,s) := Q(i − 1, s) or (xi == s) or Q(i − 1, s − xi) for A ≤ s ≤ B
Unless there are unstated constraints, the problem is NP-Hard by polynomial-time reduction of Subset-Sum, an NP-Complete problem.
One of the decision forms of Subset-Sum asks, given a set of integers, X, and an integer s, does any non-empty subset sum to s.
For each element of X, construct a Point whose x value is the element, and whose y value is zero. Construct one additional Point, whose x value is 0 and whose y value is s.
If the result of the equal-sum problem applied to that set of points is 0 or -1, then reject the subset-sum problem. If the result is s, then accept the subset-sum.
Assuming P != NP, or at least that we don't have any polynomial algorithm for any NP-Hard problem, there is no known polynomial-time algorithm for your problem.
just trying to code in java which would be helpful i felt:
for all i , diffOfCoordinates[i] = Xi - Yi
list will have the max points.
public void fun(int[] diffOfCoordinates, int indexA, int[] b, int indexB, int sum, List<Integer> list){
if(indexA == diffOfCoordinates.length){
if(sum==0){
if(list.size()<indexB){
list.clear();
for(int i=0;i<indexB;i++){
list.add(b[i]);
}
}
}
return;
}
b[indexB] = diffOfCoordinates[indexA];
fun(diffOfCoordinates, indexA+1, b, indexB+1, sum+diffOfCoordinates[indexA], list);
fun(diffOfCoordinates, indexA+1, b, indexB, sum, list);
}

Generate random numbers in increments

I need to generate n random numbers between a and b, but any two numbers cannot have a difference of less than c. All variables except n are floats (n is an int).
Solutions are preferred in java, but C/C++ is okay too.
Here is what code I have so far.:
static float getRandomNumberInRange(float min, float max) {
return (float) (min + (Math.random() * (max - min)));
}
static float[] randomNums(float a, float b, float c, int n) {
float minDistance = c;
float maxDistance = (b - a) - (n - 1) * c;
float[] randomNumArray = new float[n];
float random = getRandomNumberInRange(minDistance, maxDistance);
randomNumArray[0] = a + random;
for (int x = 1; x < n; x++) {
maxDistance = (b - a) - (randomNumArray[x - 1]) - (n - x - 1) * c;
random = getRandomNumberInRange(minDistance, maxDistance);
randomNumArray[x] = randomNumArray[x - 1] + random;
}
return randomNumArray;
}
If I run the function as such (10 times), I get the following output:
Input: randomNums(-1f, 1f, 0.1f, 10)
[-0.88, 0.85, 1.23, 1.3784, 1.49, 1.59, 1.69, 1.79, 1.89, 1.99]
[-0.73, -0.40, 0.17, 0.98, 1.47, 1.58, 1.69, 1.79, 1.89, 1.99]
[-0.49, 0.29, 0.54, 0.77, 1.09, 1.56, 1.69, 1.79, 1.89, 1.99]
I think a reasonable approach can be the following:
Total "space" is (b - a)
Remove the minimum required space (n-1)*c to obtain the remaining space
Shot (n-1) random numbers between 0 and 1 and scale them so that the sum is this just computed "optional space". Each of them will be a "slice" of space to be used.
First number is a
For each other number add c and the next "slice" to the previous number. Last number will be b.
If you don't want first and last to match a and b exactly then just create n+1 slices instead of n-1 and start with a+slice[0] instead of a.
The main idea is that once you remove the required spacing between the points (totalling (n-1)*c) the problem is just to find n-1 values so that the sum is the prescribed "optional space". To do this with a uniform distribution just shoot n-1 numbers, compute the sum and uniformly scale those numbers so that the sum is instead what you want by multiplying each of them by the constant factor k = wanted_sum / current_sum.
To obtain the final result you just use as spacing between a value and the previous one the sum of the mandatory part c and one of the randomly sampled variable parts.
An example in Python of the code needed for the computation is the following
space = b - a
slack = space - (n - 1)*c
slice = [random.random() for i in xrange(n-1)] # Pick (n-1) random numbers 0..1
k = slack / sum(slice) # Compute needed scaling
slice = [x*k for x in slice] # Scale to get slice sizes
result = [a]
for i in xrange(n-1):
result.append(result[-1] + slice[i] + c)
If you have random number X and you want another random number Y which is a minimum of A from X and a maximum of B from X, why not write that in your code?
float nextRandom(float base, float minDist, float maxDist) {
return base + minDist + (((float)Math.random()) * (maxDist - minDist));
}
by trying to keep the base out of the next number routine, you add a lot of complexity to your algorithm.
Though this does not exactly do what you need and does not incorporate the techinque being described in this thread, I believe that this code will prove to be useful as it will do what it seems like you want.
static float getRandomNumberInRange(float min, float max)
{
return (float) (min + (Math.random() * ((max - min))));
}
static float[] randomNums(float a, float b, float c, int n)
{
float averageDifference=(b-a)/n;
float[] randomNumArray = new float[n];
int random;
randomNumArray[0]=a+averageDifference/2;
for (int x = 1; x < n; x++)
randomNumArray[x]=randomNumArray[x-1]+averageDifference;
for (int x = 0; x < n; x++)
{
random = getRandomNumberInRange(-averageDifference/2, averageDifference/2);
randomNumArray[x]+=random;
}
return randomNumArray;
}
I need to generate n random numbers between a and b, but any two numbers cannot have a difference of less than c. All variables except n are floats (n is an int).
Solutions are preferred in java, but C/C++ is okay too.
First, what distribution? I'm going to assume a uniform distribution, but with that caveat that "any two numbers cannot have a difference of less than c". What you want is called "rejection sampling". There's a wikipedia article on the subject, plus a whole lot of other references on the 'net and in books (e.g. http://www.columbia.edu/~ks20/4703-Sigman/4703-07-Notes-ARM.pdf). Pseudocode, using some function random_uniform() that returns a random number drawn from U[0,1], and assuming a 1-based array (many languages use a 0-based array):
function generate_numbers (a, b, c, n, result)
result[1] = a + (b-a)*random_uniform()
for index from 2 to n
rejected = true
while (rejected)
result[index] = a + (b-a)*random_uniform()
rejected = abs (result[index] < result[index-1]) < c
end
end
Your solution was almost correct, here is the fix:
maxDistance = b - (randomNumArray[x - 1]) - (n - x - 1) * c;
I would do this by just generating n random numbers between a and b. Then I would sort them and get the first order differences, kicking out any numbers that generate a difference less than c, leaving me with m numbers. If m < n, I would just do it again, this time for n - m numbers, add those numbers to my original results, sort again, generate differences...and so on until I have n numbers.
Note, first order differences means x[1] - x[0], x[2] - x[1] and so on.
I don't have time to write this out in C but in R, it's pretty easy:
getRands<-function(n,a,b,c){
r<-c()
while(length(r) < n){
r<-sort(c(r,runif(n,a,b)))
r<-r[-(which(diff(r) <= c) + 1 )]
}
r
}
Note that if you are too aggresive with c relative to a and b, this kind of solution might take a long time to converge, or not converge at all if n * C > b -a
Also note, I don't mean for this R code to be a fully formed, production ready piece of code, just an illustration of the algorithm (for those who can follow R).
How about using a shifting range as you generate numbers to ensure that they don't appear too close?
static float[] randomNums(float min, float max, float separation, int n) {
float rangePerNumber = (max - min) / n;
// Check separation and range are consistent.
assert (rangePerNumber >= separation) : "You have a problem.";
float[] randomNumArray = new float[n];
// Set range for first random number
float lo = min;
float hi = lo + rangePerNumber;
for (int i = 0; i < n; ++i) {
float random = getRandomNumberInRange(lo, hi);
// Shift range for next random number.
lo = random + separation;
hi = lo + rangePerNumber;
randomNumArray[i] = random;
}
return randomNumArray;
}
I know you already accepted an answer, but I like this problem. I hope it's unique, I haven't gone through everyone's answers in detail just yet, and I need to run, so I'll just post this and hope it helps.
Think of it this way: Once you pick your first number, you have a chunk +/- c that you can no longer pick in.
So your first number is
range1=b-a
x=Random()*range1+a
At this point, x is somewhere between a and b (assuming Random() returns in 0 to 1). Now, we mark out the space we can no longer pick in
excludedMin=x-c
excludedMax=x+c
If x is close to either end, then it's easy, we just pick in the remaining space
if (excludedMin<=a)
{
range2=b-excludedMax
y=Random()*range2+excludedMax
}
Here, x is so close to a, that you won't get y between a and x, so you just pick between x+c and b. Likewise:
else if (excludedMax>=b)
{
range2=excludedMin-a
y=Random()*range2+a
}
Now if x is somewhere in the middle, we have to do a little magic
else
{
range2=b-a-2*c
y=Random()*range2+a
if (y>excludedMin) y+=2*c
}
What's going on here? Well, we know that the range y can lie in, is 2*c smaller than the whole space, so we pick a number somewhere in that smaller space. Now, if y is less than excludedMin, we know y "is to the left" of x-c, and we're all ok. However, if y>excluded min, we add 2*c (the total excluded space) to it, to ensure that it's greater than x+c, but it'll still be less than b because our range was reduced.
Now, it's easy to expand so n numbers, each time you just reduce the range by the excluded space among any of the other points. You continue until the excluded space equals the original range (b-a).
I know it's bad form to do a second answer, but I just thought of one...use a recursive search of the space:
Assume a global list of points: points
FillRandom(a,b,c)
{
range=b-a;
if (range>0)
{
x=Random()*range+a
points.Append(x)
FillRandom(a,x-c,c)
FillRandom(x+c,b,c)
}
}
I'll let you follow the recursion, but at the end, you'll have a list in points that fills the space with density 1/c

Clojure/Java Mandelbrot Fractal drawing

I am trying to port this algorithm to clojure.
My code is
(defn calc-iterations [x y]
(let [c (struct complex x y)]
(loop [z (struct complex 0 0)
iterations 0]
(if (and (< 2.0 (abs z))
(> max-iterations iterations))
iterations
(recur (add c (multiply z z)) (inc iterations))))))
Multiply, add and abs functions are working as they should. I have tested them with a calculator. However for the following values:
(calc-iterations 0.60703135 -0.33984375) ; should give me 2, instead I get 4
(calc-iterations -1.8421874 0.3515625 ) ; should give me 1, instead I get 3
I am checking the correct iteration numbers using another java applet that I have found on the net. it seems to be working since it produces correct output. Its iteration function is
protected int calcIterations( float x, float y ) {
int iterations = 0;
float xn = x, yn = y;
while ( iterations < MAX_ITERATIONS ) {
float xn1 = xn*xn - yn*yn;
float yn1 = 2*xn*yn;
xn = xn1 + x;
yn = yn1 + y;
float magsq = xn*xn + yn*yn;
if ( magsq > 4 )
break;
iterations++;
}
System.out.println( x + " " + y + " " + iterations );
return iterations;
}
Can anyone spot my error?
I've spotted two differences.
The Java implementation starts at z = (x, y) rather than yours which starts at (0, 0). As your recursive formula is z = z^2 + c, (0, 0)^2 + (x, y) = (x, y) so starting at (x, y) is the same as doing the first iteration. So the number of iterations will come out one less than yours because of this.
The Java implementation increments the number of iterations after checking whether the result, z, is within 2 units from the origin, and doesn't increment it otherwise, whereas yours increments iterations every time. The number of iterations will come out one less than yours because of this also.
So that probably accounts for the differences in your results.
I'd argue that your implementation is more correct, because it distinguishes between the cases where |z| > 2 after one iteration (i.e. where |(x,y)| > 2), and where |z| > 2 after two iterations (i.e. where |(x^2-y^2+x, 2xy+y)| > 2), whereas the Java implementation will perform its first iteration, giving (x^2-y^2+x, 2xy+y), and exit before incrementing the number of iterations, thus not distinguishing between that case.

Categories