simplifying fractions in Java - java

My task is to develop a rational class. If 500 and 1000 are my inputs, then (½) must be my output.
I have written a program on my own to find it.
Is there another best way to find the solution, or my program is already the best one?
public class Rational {
public static void main(String[] args){
int n1 = Integer.parseInt(args[0]);
int n2 = Integer.parseInt(args[1]);
int temp1 = n1;
int temp2 = n2;
while (n1 != n2){
if(n1 > n2)
n1 = n1 - n2;
else
n2 = n2 - n1;
}
int n3 = temp1 / n1 ;
int n4 = temp2 / n1 ;
System.out.print("\n Output :\n");
System.out.print(n3 + "/" + n4 + "\n\n" );
System.exit(0);
}
}

Interesting question. Here's some executable code that does it with minimal code:
/** #return the greatest common denominator */
public static long gcd(long a, long b) {
return b == 0 ? a : gcd(b, a % b);
}
public static String asFraction(long a, long b) {
long gcd = gcd(a, b);
return (a / gcd) + "/" + (b / gcd);
}
// Some tests
public static void main(String[] args) {
System.out.println(asFraction(500, 1000)); // "1/2"
System.out.println(asFraction(17, 3)); // "17/3"
System.out.println(asFraction(462, 1071)); // "22/51"
}
Bonus methods:
/** #return the lowest common multiple */
public static long lcm(long a, long b) {
return a * b / gcd(a, b);
}
/** #return the greatest common denominator */
public static long gcd(List<? extends Number> numbers) {
return numbers.stream().map(Number::longValue).reduce((a, b) -> gcd(a, b)).orElseThrow(NoSuchElementException::new);
}
/** #return the lowest common multiple */
public static long lcm(List<? extends Number> numbers) {
return numbers.stream().map(Number::longValue).reduce((a, b) -> lcm(a, b)).orElseThrow(NoSuchElementException::new);
}

You need the GCD. Either use BigInteger like Nathan mentioned or if you can't, use your own.
public int GCD(int a, int b){
if (b==0) return a;
return GCD(b,a%b);
}
Then you can divide each number by the GCD, like you have done above.
This will give you an improper fraction. If you need a mixed fraction then you can get the new numbers. Example if you had 1500 and 500 for inputs you would end up with 3/2 as your answer. Maybe you want 1 1/2. So you just divide 3/2 and get 1 and then get the remainder of 3/2 which is also 1. The denominator will stay the same.
whole = x/y;
numerator x%y;
denominator = y;
In case you don't believe me that this works, you can check out
http://en.wikipedia.org/wiki/Euclidean_algorithm
I just happen to like the recursive function because it's clean and simple.
Your algorithm is close, but not exactly correct. Also, you should probably create a new function if you want to find the gcd. Just makes it a little cleaner and easier to read. You can also test that function as well.

For reference, what you implemented is the original subtractive Euclidean Algorithm to calculate the greatest common divisor of two numbers.
A lot faster version is using the remainder from integer division, e.g. % instead of - in your loop:
while (n1 != 0 && n2 != 0){
if(n1 > n2)
n1 = n1 % n2;
else
n2 = n2 % n1;
}
... and then make sure you will use the one which is not zero.
A more streamlined version would be this:
while(n1 != 0) {
int old_n1 = n1;
n1 = n2 % n1;
n2 = old_n1;
}
and then use n1. Matt's answer shows a recursive version of the same algorithm.

You should make this class something other than a container for static methods. Here is a skeleton
import java.math.BigInteger;
public class BigRational
{
private BigInteger num;
private BigInteger denom;
public BigRational(BigInteger _num, BigInteger _denom)
{
//put the negative on top
// reduce BigRational using the BigInteger gcd method
}
public BigRational()
{
this(BigInteger.ZERO, BigInteger.ONE);
}
public BigRational add(BigRational that)
{
// return this + that;
}
.
.
.
//etc
}
}

I have a similar BigRational class I use. The GcdFunction is makes use of BigInteger's gcd function:
public class GcdFunction implements BinaryFunction {
#Override
public BigRational apply(final BigRational left, final BigRational right) {
if (!(left.isInteger() && right.isInteger())) {
throw new EvaluationException("GCD can only be applied to integers");
}
return new BigRational(left.getNumerator().gcd((right.getNumerator())));
}
}
BigRational contains a BigInteger numerator and denominator. isInteger() returns true if the simplified ratio's denominator is equal to 1.

Noticed that all answers here do not mention the iterative implementation of the Euclidean algorithm.
public static long gcdLongIterative(long a, long b) {
long tmp;
while (0 != b) {
tmp = b;
b = a % b;
a = tmp;
}
return a;
}
I implemented the validation test like #Bohemian and both recursive and iterative implementations work the same, however the iterative approach is faster. The benchmarks show small improvement, but it's improvement and overall it feels better to not use the stack so much and depend fully on the Java VM to optimize its implementation depend. Even if the benchmarks would be the same I would still feel better with the iterative as that would be more portable while the recursive was only optimized by my host Java, but might not be so well optimized on other's VMs.
Benchmark results (code is on the bottom of the answer):
(100 000 000 iterations)
gcd recursive: 3113ms
gcd iterative: 3079ms
gcd BigInteger: 13672ms
Signs:
One difference I noticed (besides the performance) is that the signs are handled differently, hand implemented Euclidean algorithm gcdLong and my gcdLongIterative behave the same, but both are different from BigInteger which tends to 'keep' the signs as they are. It seems that in essence the gcd and gcdLongIterative can return a negative number, while BigInteger will return positive only.
gcdLong and gcdLongIterative implementations:
-4/-2 => 2/1
-10/200 => 1/-20
10/-200 => 1/-20
BigInteger implementation tends to 'keep' the signs:
-4/-2 => -2/-1
-10/200 => -1/20
10/-200 => 1/-20
All results when used for fractions are valid, but it's worth considering post-process normalization if you expect the numbers in a specific 'style'.
For example, if the BigInteger behavior is preferred, then just returning absolute value should be enough, like here:
public static long gcdLongIterative(long a, long b) {
long tmp;
while (0 != b) {
tmp = b;
b = a % b;
a = tmp;
}
return Math.abs(a);
}
Performance:
Inspired by #Xabster benchmark (from Java: Get Greatest Common Divisor, which method is better?) I extended it to test all 3 implementations, in some cases both recursive and iterative were performing the same, however the iterative is slightly faster in most of the cases.
The benchmark code:
import java.math.BigInteger;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
public class Test {
private static final int BENCHMARK_ITERATIONS = 100000000;
public static long gcdLong(long a, long b) {
return b == 0 ? a : gcdLong(b, a % b);
}
public static long gcdLongIterative(long a, long b) {
long tmp;
while (0 != b) {
tmp = b;
b = a % b;
a = tmp;
}
return a;
}
public static long gcdLongBigInteger(long a, long b) {
return BigInteger.valueOf(a).gcd(BigInteger.valueOf((b))).longValue();
}
public static String asFractionGcdLong(long a, long b) {
long gcd = gcdLong(a, b);
return (a / gcd) + "/" + (b / gcd);
}
public static String asFractionGcdLongIterative(long a, long b) {
long gcd = gcdLongIterative(a, b);
return (a / gcd) + "/" + (b / gcd);
}
public static String asFractionGcdLongBI(long a, long b) {
long gcd = gcdLongBigInteger(a, b);
return (a / gcd) + "/" + (b / gcd);
}
public static void test(String actual, String expected) {
boolean match = expected.equals(actual);
if (match) {
System.out.println("Actual and expected match=" + expected);
} else {
System.out.println("NO match expected=" + expected + " actual=" + actual);
}
}
public static class Values {
public long a;
public long b;
public String expected;
public Values(long a, long b, String expected) {
this.a = a;
this.b = b;
this.expected = expected;
}
}
public static void validityTest() {
List<Values> vals = new LinkedList<Values>(Arrays.asList(
new Values(500, 1000, "1/2"),
new Values(17, 3, "17/3"),
new Values(462, 1071, "22/51"),
new Values(-4, -2, "2/1"),
new Values(-10, 200, "1/-20"),
new Values(10, -200, "1/-20")
));
System.out.println("------ Recursive implementation -------");
vals.forEach(v -> test(asFractionGcdLong(v.a, v.b), v.expected));
System.out.println();
System.out.println("------ Iterative implementation -------");
vals.forEach(v -> test(asFractionGcdLongIterative(v.a, v.b), v.expected));
System.out.println();
System.out.println("------ BigInteger implementation -------");
vals.forEach(v -> test(asFractionGcdLongBI(v.a, v.b), v.expected));
System.out.println();
}
public static void benchMark() {
Random r = new Random();
long[] nums = new long[BENCHMARK_ITERATIONS];
for (int i = 0 ; i < nums.length ; i++) nums[i] = r.nextLong();
System.out.println("Waming up for benchmark...");
for (int i = 0 ; i < nums.length-1; i++) gcdLong(i, i + 1);
for (int i = 0 ; i < nums.length-1; i++) gcdLongIterative(i, i + 1);
for (int i = 0 ; i < nums.length-1; i++) gcdLongBigInteger(i, i + 1);
System.out.println("Started benchmark...");
long s = System.currentTimeMillis();
for (int i = 0 ; i < nums.length-1; i++) gcdLong(i, i + 1);
System.out.println("recursive: " + (System.currentTimeMillis() - s) + "ms");
s = System.currentTimeMillis();
for (int i = 0 ; i < nums.length-1; i++) gcdLongIterative(i, i + 1);
System.out.println("iterative: " + (System.currentTimeMillis() - s) + "ms");
s = System.currentTimeMillis();
for (int i = 0 ; i < nums.length-1; i++) gcdLongBigInteger(i, i + 1);
System.out.println("BigInteger: " + (System.currentTimeMillis() - s) + "ms");
}
public static void main(String[] args) {
validityTest();
benchMark();
}
}

Related

Calculating the product of BigInteger[]

Context: I'm trying to calculate factorials for very large n using the BigInteger class in Java (for n>100,000) and so far this what I'm doing:
Produce all primes less than or equal to n using Sieve of Erasthones
Find to which powers they will be raised.
Raise all the numbers to the respective powers.
Use a divide and conquer recursive method to multiply them all.
From the research I've done on the internet, this is asymptotically faster than simply multiplying all k up to n. However I've noticed that the slowest part of my implementation is the part where I multiply all the prime powers. My questions are:
Is there a faster way to calculate the product of lots of numbers?
Can my implementation be improved ?
Code:
public static BigInteger product(BigInteger[] numbers) {
if (numbers.length == 0)
throw new ArithmeticException("There is nothing to multiply!");
if (numbers.length == 1)
return numbers[0];
if (numbers.length == 2)
return numbers[0].multiply(numbers[1]);
BigInteger[] part1 = new BigInteger[numbers.length / 2];
BigInteger[] part2 = new BigInteger[numbers.length - numbers.length / 2];
System.arraycopy(numbers, 0, part1, 0, numbers.length / 2);
System.arraycopy(numbers, numbers.length / 2, part2, 0, numbers.length - numbers.length / 2);
return product(part1).multiply(product(part2));
}
Note that BigInteger uses the karatsuba algorithm for multiplication.
I know that there are lots of questions about calculating factorials. But mine is about calculating the product of BigIntegers for which there is not much resource. (I've seen someone say "Use Divide and Conquer method", but I don't remember where, and I haven't seen any implementation around.
One way to improve the performance is to do the following:
Sort your array of numbers you need to multiply together
Create two new lists: a and b.
For each number in the input list that you need to multiply, it is likely to appear more than once. Let's say number v_i appears n_i times. Then add v_i to the a n_i / 2 times (rounded down). If n_i is odd, add v_i once to b as well.
To compute the result, do:
BigInteger A = product(a);
BigInteger B = prudoct(b);
return a.multiply(a).multiply(b);
To see how it works, consider your input array is [2, 2, 2, 2, 3, 3, 3]. So, there are four 2s and three 3s. Arrays a and b will correspondingly be
a = [2, 2, 3]
b = [3]
Then you will recursively call to compute the product of these. Note that we reduced the number of numbers that we want to multiply from 7 to 4, almost by a factor of two. The trick here is that for numbers that occur many times, we can compute the product of only half of them, and then raise it to the power of two. Very similar to how the power of a number can be computed in O(log n) time.
I propose another idea, the pow algorithm is very fast, you can compute the all primes with the exponent, like this:
11! -> {2^10, 3^5, 5^2, 7^1, 11^1}
You can compute all primes power , and then use divide and conquer to multiply all of them.
The implementation:
private static BigInteger divideAndConquer(List<BigInteger> primesExp, int min, int max){
BigInteger result = BigInteger.ONE;
if (max - min == 1){
result = primesExp.get(min);
} else if (min < max){
int middle = (max + min)/2;
result = divideAndConquer(primesExp, min, middle).multiply(divideAndConquer(primesExp, middle, max));
}
return result;
}
public static BigInteger factorial(int n) {
// compute pairs: prime, exp
List<Integer> primes = new ArrayList<>();
Map<Integer, Integer> primeTimes = new LinkedHashMap<>();
for (int i = 2; i <= n; i++) {
int sqrt = Math.round((float) Math.sqrt(i));
int value = i;
Iterator<Integer> it = primes.iterator();
int prime = 0;
while (it.hasNext() && prime <= sqrt && value != 0) {
prime = it.next();
int times = 0;
while (value % prime == 0) {
value /= prime;
times++;
}
if (times > 0) {
primeTimes.put(prime, times + primeTimes.get(prime));
}
}
if (value > 1) {
Integer times = primeTimes.get(value);
if (times == null) {
times = 0;
primes.add(value);
}
primeTimes.put(value, times + 1);
}
}
// compute primes power:
List<BigInteger> primePows = new ArrayList<>(primes.size());
for (Entry<Integer,Integer> e: primeTimes.entrySet()) {
primePows.add(new BigInteger(String.valueOf(e.getKey())).pow(e.getValue()));
}
// it multiply all of them:
return divideAndConquer(primePows, 0, primePows.size());
}
Probably the fastest approach :
Sequence.java
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public final class Sequence {
private final List<BigInteger> elements;
private Sequence(List<BigInteger> elements) {
this.elements = elements;
}
public List<BigInteger> getElements() {
return elements;
}
public int size() {
return elements.size();
}
public Sequence subSequence(int startInclusive, int endExclusive) {
return subSequence(startInclusive, endExclusive, false);
}
public Sequence subSequence(int startInclusive, int endExclusive, boolean sync) {
return Sequence.of(elements.subList(startInclusive, endExclusive), sync);
}
public void addLast(BigInteger element) {
elements.add(element);
}
public BigInteger removeLast() {
return elements.remove(size() - 1);
}
public BigInteger sum() {
return sum(false);
}
public BigInteger sum(boolean parallel) {
return parallel
? elements.parallelStream().reduce(BigInteger.ZERO, BigInteger::add)
: elements.stream().reduce(BigInteger.ZERO, BigInteger::add);
}
public BigInteger product() {
return product(false);
}
public BigInteger product(boolean parallel) {
return parallel
? elements.parallelStream().reduce(BigInteger.ONE, BigInteger::multiply)
: elements.stream().reduce(BigInteger.ONE, BigInteger::multiply);
}
public static Sequence range(int startInclusive, int endExclusive) {
return range(startInclusive, endExclusive, false);
}
public static Sequence range(int startInclusive, int endExclusive, boolean sync) {
if (startInclusive > endExclusive) {
throw new IllegalArgumentException();
}
final List<BigInteger> elements = sync ? Collections.synchronizedList(new ArrayList<>()) : new ArrayList<>();
for (; startInclusive < endExclusive; startInclusive++) {
elements.add(BigInteger.valueOf(startInclusive));
}
return new Sequence(elements);
}
public static Sequence of(List<BigInteger> elements) {
return of(elements, false);
}
public static Sequence of(List<BigInteger> elements, boolean sync) {
return new Sequence(sync ? Collections.synchronizedList(elements) : elements);
}
public static Sequence empty() {
return empty(false);
}
public static Sequence empty(boolean sync) {
return of(new ArrayList<>(), sync);
}
}
FactorialCalculator.java
import java.math.BigInteger;
import java.util.LinkedList;
import java.util.List;
public final class FactorialCalculator {
private static final int CHUNK_SIZE = Runtime.getRuntime().availableProcessors();
public static BigInteger fact(int n) {
return fact(n, false);
}
public static BigInteger fact(int n, boolean parallel) {
if (n < 0) {
throw new IllegalArgumentException();
}
if (n <= 1) {
return BigInteger.ONE;
}
Sequence sequence = Sequence.range(1, n + 1);
if (!parallel) {
return sequence.product();
}
sequence = parallelCalculate(splitSequence(sequence, CHUNK_SIZE * 2));
while (sequence.size() > CHUNK_SIZE) {
sequence = parallelCalculate(splitSequence(sequence, CHUNK_SIZE));
}
return sequence.product(true);
}
private static List<Sequence> splitSequence(Sequence sequence, int chunkSize) {
final int size = sequence.size();
final List<Sequence> subSequences = new LinkedList<>();
int index = 0, targetIndex;
while (index < size) {
targetIndex = Math.min(index + chunkSize, size);
subSequences.add(sequence.subSequence(index, targetIndex, true));
index = targetIndex;
}
return subSequences;
}
private static Sequence parallelCalculate(List<Sequence> sequences) {
final Sequence result = Sequence.empty(true);
sequences.parallelStream().map(s -> s.product(true)).forEach(result::addLast);
return result;
}
}
Test :
public static void main(String[] args) {
// warm up
for (int i = 0; i < 100; i++) {
FactorialCalculator.fact(10000);
}
int n = 1000000;
long start = System.currentTimeMillis();
FactorialCalculator.fact(n, true);
long end = System.currentTimeMillis();
System.out.printf("Execution time = %d ms", end - start);
}
Result :
Execution time = 3066 ms
OS : Win 10 Pro 64-bit
CPU : Intel Core i7-4700HQ # 2.40GHz 2.40GHz

Codility: Condition in comfort

While conducting the examination this was one of the task (which I could not solve):
They say a number A "comfort" to another number B if, when you convert both numbers to binary, all positions in B where there is a number 1 must be another 1 in the same position in A.
example:
B = 101
A = 111
In this case, the number A "comfort" to B, however
B = 101
A = 011
The Comfort condition is not met.
They gave me 3 unsigned numbers with 30 bits A, B and C, between 0 and 2 ^ 30. I must determine the amount of numbers in that range that meet the condition of "comfort" for at least one of those numbers.
expected worst-case time complexity is O (log (A) + log (B) + log (C));
I use the following code and it takes too long, most of all because it checks the binary number as an array and compare every cell. I assume there must be some way to make it faster (some math operation or idk :-( ).
public class Main {
public static void main(String[] args)
{
sol(905,5000,11111111); //I used any numbers
}
public static void sol(int A, int B, int C)
{
int min=Math.min(A, Math.min(B, C));
int max=(int) Math.pow(2, 30);
String binA=Integer.toBinaryString(A); binA=fillBin(binA);
String binB=Integer.toBinaryString(B); binB=fillBin(binB);
String binC=Integer.toBinaryString(C); binC=fillBin(binC);
String binMax=Integer.toBinaryString(max);
int conta=0;
for(int i=min;i<=max;i++)
{
String binT = Integer.toBinaryString(i);binT=fillBin(binT);
boolean failA=false;
boolean failB=false;
boolean failC=false;
for(int j=0;j<binT.length();j++)
{
if((binA.length()<j)&&(binB.length()<j)&&(binC.length()<j))
{
break;
}
if((!failA)||(!failB)||(!failC))
{
if((binA.length()<j)&&(binA.charAt(j)=='1') && (binT.charAt(j)!='1'))
{
failA=true;
}
if((binB.length()<j)&&(binB.charAt(j)=='1') && (binT.charAt(j)!='1'))
{
failB=true;
}
if((binC.length()<j)&&(binC.charAt(j)=='1') && (binT.charAt(j)!='1'))
{
failC=true;
}
}
else
{
break;
}
}
if((!failA)||(!failB)||(!failC))
{
conta++;
}
}
}
private static String fillBin(String binA)
{
String S=binA;
for(int i=0;i<(31-binA.length());i++)
{
S="0"+S;
}
return S;
}
}
If any of you already done this task before and see that there are some missing data , let me know , excuse my English (not my native language).
thank you very much
EDIT: This is the code with #Eran 's help:
public class BinaryTask
{
public void test(int A, int B, int C)
{
long timeStart, timeEnd;
timeStart = System.currentTimeMillis();
//Bunch of variables
String binaryA = Integer.toBinaryString(A); int zerosA=0;
String binaryB = Integer.toBinaryString(B); int zerosB=0;
String binaryC = Integer.toBinaryString(C); int zerosC=0;
String binaryAB =""; int zerosAB=0;
String binaryBC =""; int zerosBC=0;
String binaryAC =""; int zerosAC=0;
String binaryABC=""; int zerosABC=0;
//The long for the for
int Max = Math.max(binaryA.length(), Math.max(binaryB.length(), binaryC.length()));
//Creating: A|B, B|C, A|B and A|B|C that meet the confort condition
for(int i=0;i<Max;i++)
{
//Creating A|B
if((binaryA.length()>i)&&(binaryB.length()>i))
{
if((binaryA.charAt(i)=='1')||(binaryB.charAt(i)=='1'))
{
binaryAB="1"+binaryAB;
}
else //I also count this zero so i dont have the do another for later
{
binaryAB="0"+binaryAB; zerosAB++;
}
}
//Creating B|C
if((binaryB.length()>i)&&(binaryC.length()>i))
{
if((binaryB.charAt(i)=='1')||(binaryC.charAt(i)=='1'))
{
binaryBC="1"+binaryBC;
}else{binaryBC="0"+binaryBC; zerosBC++;}
}
//Creating A|C
if((binaryA.length()>i)&&(binaryC.length()>i))
{
if((binaryA.charAt(i)=='1')||(binaryC.charAt(i)=='1'))
{
binaryAC="1"+binaryAC;
}else{binaryAC="0"+binaryAC;zerosAC++;}
}
//Creating A|B|C
if((binaryA.length()>i)&&(binaryB.length()>i)&&(binaryC.length()>i))
{
if((binaryA.charAt(i)=='1')||(binaryB.charAt(i)=='1')||(binaryC.charAt(i)=='1'))
{
binaryABC="1"+binaryABC;
}else{binaryABC="0"+binaryABC; zerosABC++;}
}
}
//Counting the other amount of zeros
zerosA = countZeros(binaryA);
zerosB = countZeros(binaryB);
zerosC = countZeros(binaryC);
long confortA = (long) Math.pow(2, zerosA);
long confortB = (long) Math.pow(2, zerosB);
long confortC = (long) Math.pow(2, zerosC);
long confortAB = (long) Math.pow(2, zerosAB);
long confortBC = (long) Math.pow(2, zerosBC);
long confortAC = (long) Math.pow(2, zerosAC);
long confortABC = (long) Math.pow(2, zerosABC);
long totalConfort = confortA + confortB + confortC - confortAB - confortBC - confortAC + confortABC;
timeEnd = System.currentTimeMillis();
System.out.println("Total of confort for A "+A+" B "+B+" C "+C+" is " +totalConfort);
System.out.println("the task has taken "+ ( timeEnd - timeStart ) +" milliseconds");
}
private int countZeros(String binary)
{
int count=0;
for(int i=0;i<binary.length();i++)
{
if(binary.charAt(i)=='0')
{count++;}
}
return count;
}
}
To make a test, i did this:
public static void main(String[] args)
{
BinaryTask T = new BinaryTask();
int A = (int) Math.pow(2, 10);
int B = (int) Math.pow(2, 15);
int C = (int) Math.pow(2, 30);
T.test(A, B, C);
}
And this was the output:
Total of confort for A 1024 B 32768 C 1073741824 is 1073739776
the task has taken 1 milliseconds
Building on #alain's answer, comf(A) = 2^(number of zero bits in A) is the number of comforting numbers for A.
You need the number of comforting numbers for either A, B or C.
That's comf(A)+comf(B)+comf(C)-comf(A and B)-comf(B and C)-comf(A and C)+comf(A and B and C).
where comf(A and B) denotes the number of comforting numbers for both A and B.
and comf(A and B and C) denotes the number of comforting numbers for all A, B and C.
We know how to calculate comf(A), comf(B) and comf(C).
comf(A and B) = 2^(number of zero bits in A|B), since a number X comforts both A and B if and only if it has ones in all the bits for which either A or B has ones.
Similarly, comf(A and B and C) = 2^(number of zero bits in A|B|C).
Since all the calculations are bit operations on A,B and C, the running time is the lengths in bits of A, B and C, which is O (log (A) + log (B) + log (C)).
The condition for 'A comfort to B' is
B & A == B
You could just count the number n of 0 bits in B, and then you have 2^n or Math.pow(2, n) possibilities to build a 'comforting' number A.
Unfortunately, this doesn't work for 'comforting to at least one of three numbers', but it could be a starting point.
Are you sure the output Total of confort for A 1024 B 32768 C 1073741824 is 1073739776 is correct ?
I do agree with bitwise operation, with that I am getting different retult btw.
public static int solution(int A,int B,int C){
int total = 0;
int totalA=0,totalB=0,totalC=0;
//int max = Math.max(Math.max(A, B), C);
double limit = Math.pow(2,30);
for(int i=0;i<=limit;i++){
int no = A & i;
if(no == A){
total++;
totalA++;
//continue;
}
no = B & i;
if(no == B){
total++;
totalB++;
//continue;
}
no = C & i;
if(no == C){
total++;
totalC++;
//continue;
}
}
System.out.println("totalA: " + totalA + " totalB: " + totalB + " totalC: " + totalC);
total = totalA + totalB + totalC;
return total;
}
It gives me totalA: 536870912 totalB: 536870912 totalC: 1
1073741825

How to write a function that can calculate power in Java. No loops

I've been trying to write a simple function in Java that can calculate a number to the nth power without using loops.
I then found the Math.pow(a, b) class... or method still can't distinguish the two am not so good with theory. So i wrote this..
public static void main(String[] args) {
int a = 2;
int b = 31;
System.out.println(Math.pow(a, b));
}
Then i wanted to make my own Math.pow without using loops i wanted it to look more simple than loops, like using some type of Repeat I made a lot of research till i came across the commons-lang3 package i tried using StringUtils.repeat
So far I think this is the Syntax:-
public static String repeat(String str, int repeat)
StringUtils.repeat("ab", 2);
The problem i've been facing the past 24hrs or more is that StringUtils.repeat(String str, int 2); repeats strings not out puts or numbers or calculations.
Is there anything i can do to overcome this or is there any other better approach to creating a function that calculates powers?
without using loops or Math.pow
This might be funny but it took me while to figure out that StringUtils.repeat only repeats strings this is how i tried to overcome it. incase it helps
public static int repeat(int cal, int repeat){
cal = 2+2;
int result = StringUtils.repeat(cal,2);
return result;
}
can i not use recursion maybe some thing like this
public static RepeatThis(String a)
{
System.out.println(a);
RepeatThis(a);
}
just trying to understand java in dept thanks for all your comments even if there were syntax errors as long as the logic was understood that was good for me :)
Another implementation with O(Log(n)) complexity
public static long pow(long base, long exp){
if(exp ==0){
return 1;
}
if(exp ==1){
return base;
}
if(exp % 2 == 0){
long half = pow(base, exp/2);
return half * half;
}else{
long half = pow(base, (exp -1)/2);
return base * half * half;
}
}
Try with recursion:
int pow(int base, int power){
if(power == 0) return 1;
return base * pow(base, --power);
}
Function to handle +/- exponents with O(log(n)) complexity.
double power(double x, int n){
if(n==0)
return 1;
if(n<0){
x = 1.0/x;
n = -n;
}
double ret = power(x,n/2);
ret = ret * ret;
if(n%2!=0)
ret = ret * x;
return ret;
}
This one handles negative exponential:
public static double pow(double base, int e) {
int inc;
if(e <= 0) {
base = 1.0 / base;
inc = 1;
}
else {
inc = -1;
}
return doPow(base, e, inc);
}
private static double doPow(double base, int e, int inc) {
if(e == 0) {
return 1;
}
return base * doPow(base, e + inc, inc);
}
I think in Production recursion just does not provide high end performance.
double power(double num, int exponent)
{
double value=1;
int Originalexpn=exponent;
double OriginalNumber=num;
if(exponent==0)
return value;
if(exponent<0)
{
num=1/num;
exponent=abs(exponent);
}
while(exponent>0)
{
value*=num;
--exponent;
}
cout << OriginalNumber << " Raised to " << Originalexpn << " is " << value << endl;
return value;
}
Use this code.
public int mypow(int a, int e){
if(e == 1) return a;
return a * mypow(a,e-1);
}
Sure, create your own recursive function:
public static int repeat(int base, int exp) {
if (exp == 1) {
return base;
}
return base * repeat(base, exp - 1);
}
Math.pow(a, b)
Math is the class, pow is the method, a and b are the parameters.
Here is a O(log(n)) code that calculates the power of a number. Algorithmic technique used is divide and conquer. It also accepts negative powers i.e., x^(-y)
import java.util.Scanner;
public class PowerOfANumber{
public static void main(String args[]){
float result=0, base;
int power;
PowerOfANumber calcPower = new PowerOfANumber();
/* Get the user input for the base and power */
Scanner input = new Scanner(System.in);
System.out.println("Enter the base");
base=input.nextFloat();
System.out.println("Enter the power");
power=input.nextInt();
result = calcPower.calculatePower(base,power);
System.out.println(base + "^" + power + " is " +result);
}
private float calculatePower(float x, int y){
float temporary;
/* Termination condition for recursion */
if(y==0)
return 1;
temporary=calculatePower(x,y/2);
/* Check if the power is even */
if(y%2==0)
return (temporary * temporary);
else{
if(y>0)
return (x * temporary * temporary);
else
return (temporary*temporary)/x;
}
}
}
Remembering the definition of the logarithm, this can be done with ln and exp if these functions are allowed. Works for any positive base and any real exponent (not necessarily integer):
x = 6.7^4.4
ln(x) = 4.4 * ln(6.7) = about 8.36
x = exp(8.36) = about 4312.5
You can read more here and also here. Java provides both ln and exp.
A recursive method would be the easiest for this :
int power(int base, int exp) {
if (exp != 1) {
return (base * power(base, exp - 1));
} else {
return base;
}
}
where base is the number and exp is the exponenet

Java: simplest integer hash

I need a quick hash function for integers:
int hash(int n) { return ...; }
Is there something that exists already in Java?
The minimal properties that I need are:
hash(n) & 1 does not appear periodic when used with a bunch of consecutive values of n.
hash(n) & 1 is approximately equally likely to be 0 or 1.
HashMap, as well as Guava's hash-based utilities, use the following method on hashCode() results to improve bit distributions and defend against weaker hash functions:
/*
* This method was written by Doug Lea with assistance from members of JCP
* JSR-166 Expert Group and released to the public domain, as explained at
* http://creativecommons.org/licenses/publicdomain
*
* As of 2010/06/11, this method is identical to the (package private) hash
* method in OpenJDK 7's java.util.HashMap class.
*/
static int smear(int hashCode) {
hashCode ^= (hashCode >>> 20) ^ (hashCode >>> 12);
return hashCode ^ (hashCode >>> 7) ^ (hashCode >>> 4);
}
So, I read this question, thought hmm this is a pretty math-y question, it's probably out of my league. Then, I ended up spending so much time thinking about it that I actually believe I've got the answer: No function can satisfy the criteria that f(n) & 1 is non-periodic for consecutive values of n.
Hopefully someone will tell me how ridiculous my reasoning is, but until then I believe it's correct.
Here goes: Any binary integer n can be represented as either 1...0 or 1...1, and only the least significant bit of that bitmap will affect the result of n & 1. Further, the next consecutive integer n + 1 will always contain the opposite least significant bit. So, clearly any series of consecutive integers will exhibit a period of 2 when passed to the function n & 1. So then, is there any function f(n) that will sufficiently distribute the series of consecutive integers such that periodicity is eliminated?
Any function f(n) = n + c fails, as c must end in either 0 or 1, so the LSB will either flip or stay the same depending on the constant chosen.
The above also eliminates subtraction for all trivial cases, but I have not taken the time to analyze the carry behavior yet, so there may be a crack here.
Any function f(n) = c*n fails, as the LSB will always be 0 if c ends in 0 and always be equal to the LSB of n if c ends in 1.
Any function f(n) = n^c fails, by similar reasoning. A power function would always have the same LSB as n.
Any function f(n) = c^n fails, for the same reason.
Division and modulus were a bit less intuitive to me, but basically, the LSB of either option ends up being determined by a subtraction (already ruled out). The modulus will also obviously have a period equal to the divisor.
Unfortunately, I don't have the rigor necessary to prove this, but I believe any combination of the above operations will ultimately fail as well. This leads me to believe that we can rule out any transcendental function, because these are implemented with polynomials (Taylor series? not a terminology guy).
Finally, I held out hope on the train ride home that counting the bits would work; however, this is actually a periodic function as well. The way I thought about it was, imagine taking the sum of the digits of any decimal number. That sum obviously would run from 0 through 9, then drop to 1, run from 1 to 10, then drop to 2... It has a period, the range just keeps shifting higher the higher we count. We can actually do the same thing for the sum of the binary digits, in which case we get something like: 0,1,1,2,2,....5,5,6,6,7,7,8,8....
Did I leave anything out?
TL;DR I don't think your question has an answer.
[SO decided to convert my "trivial answer" to comment. Trying to add little text to it to see if it can be fooled]
Unless you need the ranger of hashing function to be wider..
The NumberOfSetBits function seems to vary quite a lot more then the hashCode, and as such seems more appropriate for your needs. Turns out there is already a fairly efficient algorithm on SO.
See Best algorithm to count the number of set bits in a 32-bit integer.
I did some experimentation (see test program below); computation of 2^n in Galois fields, and floor(A*sin(n)) both did very well to produce a sequence of "random" bits. I tried multiplicative congruential random number generators and some algebra and CRC (which is analogous of k*n in Galois fields), none of which did well.
The floor(A*sin(n)) approach is the simplest and quickest; the 2^n calculation in GF32 takes approx 64 multiplies and 1024 XORs worstcase, but the periodicity of output bits is extremely well-understood in the context of linear-feedback shift registers.
package com.example.math;
public class QuickHash {
interface Hasher
{
public int hash(int n);
}
static class MultiplicativeHasher1 implements Hasher
{
/* multiplicative random number generator
* from L'Ecuyer is x[n+1] = 1223106847 x[n] mod (2^32-5)
* http://dimsboiv.uqac.ca/Cours/C2012/8INF802_Hiv12/ref/paper/RNG/TableLecuyer.pdf
*/
final static long a = 1223106847L;
final static long m = (1L << 32)-5;
/*
* iterative step towards computing mod m
* (j*(2^32)+k) mod (2^32-5)
* = (j*(2^32-5)+j*5+k) mod (2^32-5)
* = (j*5+k) mod (2^32-5)
* repeat twice to get a number between 0 and 2^31+24
*/
private long quickmod(long x)
{
long j = x >>> 32;
long k = x & 0xffffffffL;
return j*5+k;
}
// treat n as unsigned before computation
#Override public int hash(int n) {
long h = a*(n&0xffffffffL);
long h2 = quickmod(quickmod(h));
return (int) (h2 >= m ? (h2-m) : h2);
}
#Override public String toString() { return getClass().getSimpleName(); }
}
/**
* computes (2^n) mod P where P is the polynomial in GF2
* with coefficients 2^(k+1) represented by the bits k=31:0 in "poly";
* coefficient 2^0 is always 1
*/
static class GF32Hasher implements Hasher
{
static final public GF32Hasher CRC32 = new GF32Hasher(0x82608EDB, 32);
final private int poly;
final private int ofs;
public GF32Hasher(int poly, int ofs) {
this.ofs = ofs;
this.poly = poly;
}
static private long uint(int x) { return x&0xffffffffL; }
// modulo GF2 via repeated subtraction
int mod(long n) {
long rem = n;
long q = uint(this.poly);
q = (q << 32) | (1L << 31);
long bitmask = 1L << 63;
for (int i = 0; i < 32; ++i, bitmask >>>= 1, q >>>= 1)
{
if ((rem & bitmask) != 0)
rem ^= q;
}
return (int) rem;
}
int mul(int x, int y)
{
return mod(uint(x)*uint(y));
}
int pow2(int n) {
// compute 2^n mod P using repeated squaring
int y = 1;
int x = 2;
while (n > 0)
{
if ((n&1) != 0)
y = mul(y,x);
x = mul(x,x);
n = n >>> 1;
}
return y;
}
#Override public int hash(int n) {
return pow2(n+this.ofs);
}
#Override public String toString() {
return String.format("GF32[%08x, ofs=%d]", this.poly, this.ofs);
}
}
static class QuickHasher implements Hasher
{
#Override public int hash(int n) {
return (int) ((131111L*n)^n^(1973*n)%7919);
}
#Override public String toString() { return getClass().getSimpleName(); }
}
// adapted from http://www.w3.org/TR/PNG-CRCAppendix.html
static class CRC32TableHasher implements Hasher
{
final private int table[];
static final private int polyval = 0xedb88320;
public CRC32TableHasher()
{
this.table = make_table();
}
/* Make the table for a fast CRC. */
static public int[] make_table()
{
int[] table = new int[256];
int c;
int n, k;
for (n = 0; n < 256; n++) {
c = n;
for (k = 0; k < 8; k++) {
if ((c & 1) != 0)
c = polyval ^ (c >>> 1);
else
c = c >>> 1;
}
table[n] = (int) c;
}
return table;
}
public int iterate(int state, int i)
{
return this.table[(state ^ i) & 0xff] ^ (state >>> 8);
}
#Override public int hash(int n) {
int h = -1;
h = iterate(h, n >>> 24);
h = iterate(h, n >>> 16);
h = iterate(h, n >>> 8);
h = iterate(h, n);
return h ^ -1;
}
#Override public String toString() { return getClass().getSimpleName(); }
}
static class TrigHasher implements Hasher
{
#Override public String toString() { return getClass().getSimpleName(); }
#Override public int hash(int n) {
double s = Math.sin(n);
return (int) Math.floor((1<<31)*s);
}
}
private static void test(Hasher hasher) {
System.out.println(hasher+":");
for (int i = 0; i < 64; ++i)
{
int h = hasher.hash(i);
System.out.println(String.format("%08x -> %08x %%2 = %d",
i,h,(h&1)));
}
for (int i = 0; i < 256; ++i)
{
System.out.print(hasher.hash(i) & 1);
}
System.out.println();
analyzeBits(hasher);
}
private static void analyzeBits(Hasher hasher) {
final int N = 65536;
final int maxrunlength=32;
int[][] runs = {new int[maxrunlength], new int[maxrunlength]};
int[] count = new int[2];
int prev = -1;
System.out.println("Run length test of "+N+" bits");
for (int i = 0; i < maxrunlength; ++i)
{
runs[0][i] = 0;
runs[1][i] = 0;
}
int runlength_minus1 = 0;
for (int i = 0; i < N; ++i)
{
int b = hasher.hash(i) & 0x1;
count[b]++;
if (b == prev)
++runlength_minus1;
else if (i > 0)
{
++runs[prev][runlength_minus1];
runlength_minus1 = 0;
}
prev = b;
}
++runs[prev][runlength_minus1];
System.out.println(String.format("%d zeros, %d ones", count[0], count[1]));
for (int i = 0; i < maxrunlength; ++i)
{
System.out.println(String.format("%d runs of %d zeros, %d runs of %d ones", runs[0][i], i+1, runs[1][i], i+1));
}
}
public static void main(String[] args) {
Hasher[] hashers = {
new MultiplicativeHasher1(),
GF32Hasher.CRC32,
new QuickHasher(),
new CRC32TableHasher(),
new TrigHasher()
};
for (Hasher hasher : hashers)
{
test(hasher);
}
}
}
The simplest hash for int value is the int value.
See Java Integer class
public int hashCode()
public static int hashCode(int value)
Returns:
a hash code value for this object, equal to the primitive int value represented by this Integer object.

Check if BigInteger is not a perfect square

I have a BigInteger value, let's say it is 282 and is inside the variable x. I now want to write a while loop that states:
while b2 isn't a perfect square:
a ← a + 1
b2 ← a*a - N
endwhile
How would I do such a thing using BigInteger?
EDIT: The purpose for this is so I can write this method. As the article states one must check if b2 is not square.
Compute the integer square root, then check that its square is your number. Here is my method of computing the square root using Heron's method:
private static final BigInteger TWO = BigInteger.valueOf(2);
/**
* Computes the integer square root of a number.
*
* #param n The number.
*
* #return The integer square root, i.e. the largest number whose square
* doesn't exceed n.
*/
public static BigInteger sqrt(BigInteger n)
{
if (n.signum() >= 0)
{
final int bitLength = n.bitLength();
BigInteger root = BigInteger.ONE.shiftLeft(bitLength / 2);
while (!isSqrt(n, root))
{
root = root.add(n.divide(root)).divide(TWO);
}
return root;
}
else
{
throw new ArithmeticException("square root of negative number");
}
}
private static boolean isSqrt(BigInteger n, BigInteger root)
{
final BigInteger lowerBound = root.pow(2);
final BigInteger upperBound = root.add(BigInteger.ONE).pow(2);
return lowerBound.compareTo(n) <= 0
&& n.compareTo(upperBound) < 0;
}
I found a sqrt method used here, and simplified the square test.
private static final BigInteger b100 = new BigInteger("100");
private static final boolean[] isSquareResidue;
static{
isSquareResidue = new boolean[100];
for(int i =0;i<100;i++){
isSquareResidue[(i*i)%100]=true;
}
}
public static boolean isSquare(final BigInteger r) {
final int y = (int) r.mod(b100).longValue();
boolean check = false;
if (isSquareResidue[y]) {
final BigInteger temp = sqrt(r);
if (r.compareTo(temp.pow(2)) == 0) {
check = true;
}
}
return check;
}
public static BigInteger sqrt(final BigInteger val) {
final BigInteger two = BigInteger.valueOf(2);
BigInteger a = BigInteger.ONE.shiftLeft(val.bitLength() / 2);
BigInteger b;
do {
b = val.divide(a);
a = (a.add(b)).divide(two);
} while (a.subtract(b).abs().compareTo(two) >= 0);
return a;
}
public static Boolean PerfectSQR(BigInteger A){BigInteger B=A.sqrt(), C=B.multiply(B);return (C.equals(A));}
DON'T use this...
BigInteger n = ...;
double n_as_double = n.doubleValue();
double n_sqrt = Math.sqrt(n_as_double);
BigInteger n_sqrt_as_int = new BigDecimal(n_sqrt).toBigInteger();
if (n_sqrt_as_int.pow(2).equals(n)) {
// number is perfect square
}
As Christian Semrau commented below - this doesn't work. I am sorry for posting incorrect answer.
using System.Numerics; // needed for BigInteger
/* Variables */
BigInteger a, b, b2, n, p, q;
int flag;
/* Assign Data */
n = 10147;
a = iSqrt(n);
/* Algorithm */
do
{ a = a + 1;
b2 = (a * a) – n;
b = iSqrt(b2);
flag = BigInteger.Compare(b * b, b2);
} while(flag != 0);
/* Output Data */
p = a + b;
q = a – b;
/* Method */
private static BigInteger iSqrt(BigInteger num)
{ // Finds the integer square root of a positive number
if (0 == num) { return 0; } // Avoid zero divide
BigInteger n = (num / 2) + 1; // Initial estimate, never low
BigInteger n1 = (n + (num / n)) / 2;
while (n1 < n)
{ n = n1;
n1 = (n + (num / n)) / 2;
}
return n;
} // end iSqrt()
private static boolean isSqrt(BigInteger n, BigInteger root)
{
final BigInteger lowerBound = root.pow(2);
final BigInteger upperBound = root.add(BigInteger.ONE).pow(2);
return lowerBound.compareTo(n) <= 0
&& n.compareTo(upperBound) < 0;
}
I tried the above using JavaScript BigInt:
function isPerfectSqrt(n, root) {
const lowerBound = root**2n;
const upperBound = (root+1n)**2n
return lowerBound <= n && n < upperBound;
}
And found it was only about 60% as fast (in Node V8) as the one-liner:
function isPerfectSqrt(n, root) {
return (n/root === root && n%root === 0n)
}
The number you want to do a perfect square test on is A. B is the integer square root of A and the .sqrt() function returns the integer lower floor of the square root. The Boolean of B*B=A is returned. The Boolean return is "true" if it is a perfect square and "false" if it is not a perfect square.
public static Boolean PerfectSQR(BigInteger A) {
BigInteger B = A.sqrt();
return B.multiply(B).equals(A);
}
An alternative is to use the sqrtAndRemainder() function. If the remainder, B[1], is zero it is a perfect square. The boolean TRUE then is returned as shown below.
public static Boolean PerfectSQR(BigInteger A) {
BigInteger [] B=A.sqrtAndRemainder();
return B[1].equals(BigInteger.ZERO);
}

Categories

Resources